宮沢賢治のオールナイトニッポン

アプリ開発/プログラミング学習における厄介事を垂れ流します。flutter/dart/python...

アプリからGDrive上にフォルダ作成、ファイルをアップロードする 【Google Drive API v3】

開発中のアプリでデータをCSV出力する機能を実装しました。出力先はGoogle Driveのアプリ専用フォルダです。

流れとしては、

  • csvString作成
  • 出力先のフォルダがGDrive上にあるか確認
  • (なければ、フォルダ作成)
  • csvファイルをGDrive上にアップロード

という感じになります。

csvStringの作成はいろいろな方法がありますが、僕はアプリ内のデータオブジェクトを下記のパッケージでcsvStringへ変換しました。 https://pub.dev/packages/csv

また、ここで記述した内容は API権限スコープ https://www.googleapis.com/auth/drive.file のもとで行っています。

フォルダがあるかチェック -> ここでいう id はファイルやフォルダ固有のIDのことです。ファイルやフォルダ作成時にAPIから返ってくるIDを保存しておき、次回以降はそのフォルダIDを指定してやり、アプリフォルダ以下にファイルを作成していきます。

アカウント変更などの影響で,IDは持っているが現在参照しているアカウント上にはフォルダが存在しない場合があるので、フォルダ名とIDでチェックします。

  Future<bool> fileExistsOnGDrive(String fileName, String id) async {
    final client = GoogleHttpClient(await googleSignInAccount.authHeaders);
    final drive = googleApis.DriveApi(client);
    await drive.files
        .list(spaces: 'drive', $fields: 'files(id)', q: 'name = $fileName')
        .then((value) {
      if (value != null && value.files.length > 0) {
        for (var file in value.files) {
          if (file.id == id) {
            return true;
          }
        }
      }
    });
    return false;
  }

listでとれる情報は上記スコープのもとでは、アプリが作成したファイル/フォルダのみになります。

list メソッドの q パラメータ作成について -> https://developers.google.com/drive/api/v3/ref-search-terms#drive_properties

アプリフォルダ作成

    final googleApisFolder = googleApis.File();
    googleApisFolder.name = csvFolderName;
    googleApisFolder.mimeType = 'application/vnd.google-apps.folder'; // フォルダとして指定
    final response = await drive.files.create(googleApisFolder);
    final String folderID = response.id;

    await setString(key, folderID); 
    // 以降は保存したIDを指定して,フォルダ以下にファイルを作成

Google DriveにおけるmimeType について -> https://developers.google.com/drive/api/v3/mime-types

アップロード

    final csvFileToUpload = googleApis.File();
    final csvFileOnLocal = File(csvPath);

    csvFileToUpload.parents = [folderID]; // 保存しておいたフォルダIDを指定する。
    csvFileToUpload.name = path.basename(csvPath);

    final response = await drive.files.create(
        csvFileToUpload,
        uploadMedia: googleApis.Media(file.openRead(), file.lengthSync()),
      );

以上がざっくりとしたフォルダ作成 -> ファイルアップロードの流れでした。 listcreateのパラメータをもっと読むと、さらに便利な使い方、リファクタが可能かと思います。

Google Drive API Docsを初めて見たときは情報量に圧倒されましたが、丁寧にわかりやすく、かつ情報を網羅しており(docsなのであたりまえ?)、非常にためになりました。

参考 :

drive.files.list -> https://developers.google.com/drive/api/v3/reference/files/list

drive.files.create -> https://developers.google.com/drive/api/v3/reference/files/create