【问题标题】:How do I upload a file to Google Drive using Flutter?如何使用 Flutter 将文件上传到 Google Drive?
【发布时间】:2021-01-19 00:51:51
【问题描述】:

我正在制作一个 Flutter 移动应用程序,并尝试将使用相机拍摄的图像保存到特定的 Google 驱动器帐户以进行存储。我从我的 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,但大小为空,从网络登录时,我无法在 Google 驱动器中上传文件。使用 Google Drive API 上传此文件的正确方法是什么?

【问题讨论】:

  • 为什么选择谷歌驱动器?为什么不使用谷歌存储/亚马逊网络服务 S3?
  • 您是否查看了有关如何upload and download 的googleapis 示例?
  • @dwikurniantom 我原以为 Google Drive 会更容易,因为我更熟悉它,但似乎并非如此,所以我会研究这些替代方案。谢谢!
  • @Kessy 谢谢!我一直在关注 Medium 上的一些教程,但没有找到。

标签: flutter google-drive-api


【解决方案1】:

这很容易,但您必须经过一系列步骤才能完成。

1.启用 Google Drive API

点击链接到谷歌控制台: 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);
    }

  }




}

【讨论】:

    【解决方案2】:

    事实证明,除了启用 API 和创建服务帐户之外,我还需要与来自 JSON 的服务帐户电子邮件地址共享我想上传到的文件夹。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-06
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-20
      • 1970-01-01
      • 2020-03-10
      相关资源
      最近更新 更多