如何使用Flutter将文件上传到Google云端硬盘?

w8biq8rn  于 2023-05-23  发布在  Flutter
关注(0)|答案(3)|浏览(209)

我正在制作一个Flutter移动的应用程序,并试图将用相机拍摄的图像保存到特定的Google Drive帐户中进行存储。我已经从我的Google帐户中获取了一个服务帐户JSON文件来进行身份验证。
这是我使用的代码:

import 'dart:io' as io;
import 'package:googleapis/drive/v3.dart' as ga;
import 'package:googleapis_auth/auth.dart';
import 'package:googleapis_auth/auth_io.dart';

uploadFileToGoogleDrive(io.File fileToUpload) async {

  // send authorization to access Google Drive
  // from https://pub.dev/packages/googleapis_auth

  ServiceAccountCredentials accountCredentials = new ServiceAccountCredentials.fromJson({
//my service account JSON information goes here
  });
  List<String> scopes = [ga.DriveApi.DriveFileScope, ga.DriveApi.DriveScope];

 
    try {
      // authenticates with Google Drive with our service account credentials
      AuthClient client = await clientViaServiceAccount(
          accountCredentials, scopes);

      ga.DriveApi drive = ga.DriveApi(client);
      ga.File file = ga.File(); // create new file record to upload to Drive
      try {
        file.name = 'image.jpg';
        
        ga.File response = await drive.files.create(file, uploadMedia: ga.Media(
            fileToUpload.openRead(), fileToUpload.lengthSync()));
   
        print('uploaded with a file size of: ${response.size}');
      } on Exception catch (e) {
        print('upload error: $e');
      }
      client.close();
    } on Exception catch (e) {
      print('credentials error: $e');
    }
  
}

我上传的文件大小为24095。不返回错误消息。返回的“响应”有一个Google驱动器文件ID,但大小为null,从Web登录时,我无法在Google驱动器中上传文件。使用Google云端硬盘API上传此文件的正确方法是什么?

r6vfmomb

r6vfmomb1#

这很容易,但你必须通过一系列的步骤来完成它。

1.启用Google Drive API

点击Google Console的链接:https://console.developers.google.com/apis/library?project=diary-app-339509

  • 创建一个新项目并在项目上启用Drive API。
  • 为android和IOS创建OAuth客户端ID
  • 你将不得不填写大量的细节来创建它,通读页面并填写
  • 复制客户端ID以备将来使用

create project and enable API
Create OAuth client id
form to fill to make OAuth client id

2.对外开放项目。

for testing add test user email address

  • 现在是Flutter的编码部分 *
    *3.将以下包添加到 pubspec.yaml
googleapis: ^7.0.0
  googleapis_auth: ^1.3.0
  flutter_secure_storage: ^5.0.2
  url_launcher: ^6.0.0-nullsafety

4.从google获取身份验证,并存储Auth详细信息以备将来验证

使用以下类存储身份验证详细信息

import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:googleapis_auth/auth_io.dart';

class SecureStorage {
  final storage = FlutterSecureStorage();

  //Save Credentials
  Future saveCredentials(AccessToken token, String refreshToken) async {
    print(token.expiry.toIso8601String());
    await storage.write(key: "type", value: token.type);
    await storage.write(key: "data", value: token.data);
    await storage.write(key: "expiry", value: token.expiry.toString());
    await storage.write(key: "refreshToken", value: refreshToken);
  }

  //Get Saved Credentials
  Future<Map<String, dynamic>?> getCredentials() async {
    var result = await storage.readAll();
    if (result.isEmpty) return null;
    return result;
  }

  //Clear Saved Credentials
  Future clear() {
    return storage.deleteAll();
  }
}

5.最后使用这个类将文件保存到驱动器

import 'dart:io';
import 'package:googleapis/drive/v3.dart' as ga;
import 'package:googleapis_auth/auth_io.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as p;
import 'package:personal_diary/app/utils/secure_storage.dart';
import 'package:url_launcher/url_launcher.dart';

const _clientId = "YOUR CLIENT ID FROM GOOGLE CONSOLE";
const _scopes = ['https://www.googleapis.com/auth/drive.file'];

class GoogleDrive {
  final storage = SecureStorage();
  //Get Authenticated Http Client
  Future<http.Client> getHttpClient() async {
    //Get Credentials
    var credentials = await storage.getCredentials();
    if (credentials == null) {
      //Needs user authentication
      var authClient = await clientViaUserConsent(
          ClientId(_clientId),_scopes, (url) {
        //Open Url in Browser
        launch(url);
      });
      //Save Credentials
      await storage.saveCredentials(authClient.credentials.accessToken,
          authClient.credentials.refreshToken!);
      return authClient;
    } else {
      print(credentials["expiry"]);
      //Already authenticated
      return authenticatedClient(
          http.Client(),
          AccessCredentials(
              AccessToken(credentials["type"], credentials["data"],
                  DateTime.tryParse(credentials["expiry"])!),
              credentials["refreshToken"],
              _scopes));
    }
  }

// check if the directory forlder is already available in drive , if available return its id
// if not available create a folder in drive and return id
//   if not able to create id then it means user authetication has failed
  Future<String?> _getFolderId(ga.DriveApi driveApi) async {
    final mimeType = "application/vnd.google-apps.folder";
    String folderName = "personalDiaryBackup";

    try {
      final found = await driveApi.files.list(
        q: "mimeType = '$mimeType' and name = '$folderName'",
        $fields: "files(id, name)",
      );
      final files = found.files;
      if (files == null) {
        print("Sign-in first Error");
        return null;
      }

      // The folder already exists
      if (files.isNotEmpty) {
        return files.first.id;
      }

      // Create a folder
      ga.File folder = ga.File();
      folder.name = folderName;
      folder.mimeType = mimeType;
      final folderCreation = await driveApi.files.create(folder);
      print("Folder ID: ${folderCreation.id}");

      return folderCreation.id;
    } catch (e) {
      print(e);
      return null;
    }
  }

  
  uploadFileToGoogleDrive(File file) async {
    var client = await getHttpClient();
    var drive = ga.DriveApi(client);
    String? folderId =  await _getFolderId(drive);
    if(folderId == null){
      print("Sign-in first Error");
    }else {
      ga.File fileToUpload = ga.File();
      fileToUpload.parents = [folderId];
      fileToUpload.name = p.basename(file.absolute.path);
      var response = await drive.files.create(
        fileToUpload,
        uploadMedia: ga.Media(file.openRead(), file.lengthSync()),
      );
      print(response);
    }

  }



}
bvn4nwqk

bvn4nwqk2#

结果发现,除了启用API和创建服务帐户之外,我还需要从JSON共享我想要上传到服务帐户电子邮件地址的文件夹。

cpjpxq1n

cpjpxq1n3#

我最近得到了这个错误,我努力尝试,终于解决了它。错误是由于SHA-1密钥不匹配。请转到您的Android目录并在其中使用./gradlew signingReport =>命令。

相关问题