Ruby で Google::Apis::DriveV3 を用いて Google Drive のファイルを操作する方法

前提条件

  • サービスアカウントを用いて認証を行うとします

使う gem

  • google-api-client
    • google-apis-sheets_v4 でもいいですが、名前が適切な方が誰からも分かりやすいので google-api-client がよいと思います

注意事項

  • 当該ドライブ(フォルダ等)に、サービスアカウントによるアクセス権限を予め付与しておくこと*1
  • 認証コードでは require 'google/apis/drive_v3' を明示的に書くこと*2

具体的方法

認証

いつものやりかたです。スプレッドシートなどと同じです。

以下は概念的なコードですです。

require 'google/apis/drive_v3' # 重要

def create_api
  authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
    json_key_io: File.open('/path/to/credentials.json'),

    scope: %w[
      https://www.googleapis.com/auth/drive
      https://www.googleapis.com/auth/drive.file
    ]
  )
  authorizer.fetch_access_token!

  # https://googleapis.dev/ruby/google-api-client/latest/Google/Apis/DriveV3/DriveService.html
  api = Google::Apis::DriveV3::DriveService.new
  api.authorization = authorizer

  api
end

特定のフォルダ直下のファイルやフォルダを取得する

ここが最大のハマりポイントです。

結論から書くとdrive_id を親として、その親の中のファイルやフォルダを『検索する』」方法により取得します。

api = create_api
listed_files = api.list_files(q: "'ドライブID' in parents")

これで Google::Apis::DriveV3::FileList のオブジェクトが得られます。その他の実行時オプションは都合に応じて用います。ただし、corpora を指定してしまうとなぜか drive_id が正しくても認証できません*3

ここさえできれば後は大丈夫でしょう。

listed_files の個々の中身を調べる

file_objects = listed_files.files

ファイルの mime_type を調べる

上記の file_objects の各要素である file_object には mime_type が定義されています。この mime_type により、そのオブジェクトがフォルダなのかファイルなのかを判別できます*4

mime_type には以下のような種類があります。この値で分岐を書けば、フォルダの中のフォルダを掘るようなコードはすぐ書けるでしょう*5

  • application/vnd.google-apps.folder
  • application/vnd.google-apps.spreadsheet
  • application/vnd.google-apps.document
  • image/png
  • image/jpeg

ファイルを作成(アップロード)する

以下のように書きます。オプションは他にもあるので後述のドキュメントを見ます。

api.create_file(
   {
     name: "file.txt",
     parents: [upload_folder_id], # 配列であることに注意
   },
   upload_source: '/path/to/sample.txt' 
 )

ファイルをダウンロードする

api.get_file(file_id, download_dest: '/tmp/foobar')

重要ドキュメント

以下のドキュメントは超重要です。これらを見れば全て書いてあります。

Google::Apis::DriveV3::DriveService

これが create_api で作られるインスタンスです。これが全てのベースです。

googleapis.dev

Google::Apis::DriveV3::FileList

list_files したときの戻り値のインスタンスが属するクラスです。

中身は次項の Class: Google::Apis::DriveV3::FileList のインスタンスが詰め込まれた配列になっています。

googleapis.dev

Google::Apis::DriveV3::File

Class: Google::Apis::DriveV3::FileList の中に詰め込まれている配列の各要素です。

たとえば以下のようなオブジェクトです。ここまで取れればあとはやりたい放題です。

   #<Google::Apis::DriveV3::File:0x00007f957321c630
    @id="1234567890",
    @kind="drive#file",
    @mime_type="image/jpeg",
    @name="my_photo.jpg">,

ファイル検索クエリ書式

ファイルを検索する際のクエリの書き方の説明です。これを見ないとファイル検索(絞り込み)が満足にできないので、一読しておいたほうがいいです。

developers.google.com

感想と結論

  • 上記のことがわかっていればだいたいのことはできる
  • しかし、コードがごちゃごちゃしてしまいそうだ
  • ラッパー gem を使いたくなるのも分かる。
    • が、だいぶメンテされていないようだし、共有フォルダ・共有ファイルを扱うにはこっちしかないっぽいと思うので、頑張ってこっちで書いたほうがいいと思う
  • ここまで面倒だと GAS でやったほうが楽なことが多いし、実際そうしている
    • GAS はドキュメントも多いし Clasp を使えばまあまあ楽

*1:忘れやすい

*2:Rails だとしても

*3:ここが最大のハマりポイント。サービスアカウントだからかも

*4:#kind というのがあるんですが、これは全て drive#file なので騙されてはいけません

*5:先ほど書いた、q: "'ドライブID' in parents" の「ドライブID」を「オブジェクトID」に変更すればいい

Powered by はてなブログ