Google Drive(docs)からrubyでファイル一覧を取得する方法

Google Drive(docs)からrubyでファイル一覧を取得する方法メモ。



Google Drive(docs)からrubyでファイル一覧を取得する方法


全体的にけっこうややこしいです。大雑把に以下の手順が必要です。


  1. Google APIのページでGoogle Drive APIを許可する
  2. client_secrets.jsonをダウンロードする
  3. rubyコードを実行する

順に説明していきます。



Google APIのページでGoogle Drive APIを許可する


Google APIのページはこちらです。

Google APIs Console


一応やるべきことは全部このREADMEに書いてあります。

github/google/google-api-ruby-client-samples


上記の資料は英語ですし情報がやや古いですが、この後ばんばん英語の情報がでてくるので上記の資料は頑張って読み解きましょう。


Google APIのページでやることは主に下記の通りです。


  • APIs & auth > APIsからGoogle Drive APIをONにする(Google Drive SDKは不要)
  • 自分のアプリケーションに名前を付ける(後述)
  • client_secrets.jsonをダウンロードする(後述)


Google APIのページからclient_secrets.jsonをダウンロードする


この手順も上記の英語の資料に書いてあります。「APIs & auth > Credentials > CREATE NEW CLIENT ID」からClient IDを作成すると、client_secrets.jsonをダウンロードするリンクが表示されます。


途中、Application TypeはInstalled Application、Installed Application TypeはOtherを選んでください。


さらにこの後、「APIs & auth > Consent screen」からProduct Nameを何か適当な値にしておくのを忘れないようにしましょう。これをしてないと後でエラーになります。



rubyコードを実行する


gemはgoogle-api-ruby-clientを使うのが現状ベストっぽいです。

github google-api-ruby-client


google-api-ruby-clientの作者(google)が、Google Driveにファイルを新規にアップロードするサンプルを公開してくれています。

github google-api-ruby-client-samples drive.rb


ただし上記のサンプルコードだけではバグが残っています。そのバグを手直しして、ファイル新規アップロードではなく、特定のフォルダのファイル一覧を取得するコードは下記の通りです。


# -*- coding: utf-8 -*-
require 'google/api_client'
require 'google/api_client/client_secrets'
require 'google/api_client/auth/file_storage'
require 'google/api_client/auth/installed_app'
require 'logger'

API_VERSION = 'v2'
CACHED_API_FILE = "drive-#{API_VERSION}.cache"
CREDENTIAL_STORE_FILE = "#{$0}-oauth2.json"

# gemにバグがあるらしく、暫定的なコードとしてこの変換がおすすめされている。
# この処理がないと、refresh_tokenを使ったtoken再取得に失敗する。
# https://github.com/google/google-api-ruby-client/issues/90
def file_format_bug_fix(credential_store_file)
  return if !File.exists?(credential_store_file)
  temp = nil 
  File.open(credential_store_file, "r") do |f| 
    temp = JSON.load(f)
    if temp["authorization_uri"].class != String
      temp["authorization_uri"] =
        "https://accounts.google.com/o/oauth2/auth"
    end 
    if temp["token_credential_uri"].class != String
      temp["token_credential_uri"] =
        "https://accounts.google.com/o/oauth2/token"
    end 
  end 
  File.open(credential_store_file, "w") do |f| 
    f.write(temp.to_json)
  end 
end

def setup()
  log_file = File.open('log/drive.log', 'a+')
  log_file.sync = true
  logger = Logger.new(log_file)
  logger.level = Logger::DEBUG

  client = Google::APIClient.new(:application_name => 'Ruby Drive sample',
      :application_version => '1.0.0')

  file_storage = Google::APIClient::FileStorage.new(CREDENTIAL_STORE_FILE)
  if file_storage.authorization.nil?
    client_secrets = Google::APIClient::ClientSecrets.load
    flow = Google::APIClient::InstalledAppFlow.new(
      :client_id => client_secrets.client_id,
      :client_secret => client_secrets.client_secret,
      :scope => ['https://www.googleapis.com/auth/drive']
    )
    client.authorization = flow.authorize(file_storage)
  else
    client.authorization = file_storage.authorization
  end

  drive = nil
  if File.exists? CACHED_API_FILE
    File.open(CACHED_API_FILE) do |file|
      drive = Marshal.load(file)
    end
  else
    drive = client.discovered_api('drive', API_VERSION)
    File.open(CACHED_API_FILE, 'w') do |file|
      Marshal.dump(drive, file)
    end
  end

  return client, drive
end

# フォルダを指定し、ファイル名を指定し、条件を満たしたファイル一覧を返す
def get_list(client, drive)
  result = client.execute(
    :api_method => drive.children.list,
    :parameters => {
      'folderId' => '検索したいフォルダのID',
      'q' => "title = 'タイトルから検索したい文字列'",
      'alt' => 'json'})

  #jj result.data.to_hash
  result.data.items
end

if __FILE__ == $0
  file_format_bug_fix(CREDENTIAL_STORE_FILE)
  client, drive = setup()
  files = get_list(client, drive)
end

上記のrubyコードでは、フォルダを指定し、ファイル名を指定し、ファイルの一覧を取得しています。APIの仕様は公式リファレンスをご参照ください。

drive.children.listのリファレンス



その他注意事項

上記のrubyコードを実行する際は、client_secrets.jsonをrubyコードと同じディレクトリに置いておくと、client_id、client_secretが自動で読み込まれます。


「Unable to find a browser command. ~ Launchy::CommandNotFoundError」の対策

上記のrubyコードをlinux上で実行する際は、まずlocalhost(macとか)で実行して、drive.rb-oauth2.jsonを生成しておき、drive.rb-oauth2.jsonをlinux上のrubyコードと同じディレクトリに置いておきましょう。初回のみブラウザでの認証が必須なため、localhostで先にdrive.rb-oauth2.jsonを生成しておく必要があります。



ご意見、ご質問


分からない点等は@ts_3156までお気軽にご質問ください(^^)



参考リンク


Google Developers API Reference

google-api-ruby-client


Google Drive(docs)からrubyでファイルを取得する方法

Google Drive(docs)からrubyでファイルをコピーする方法


著者プロフィール
Webサイトをいくつか作っています。
著者プロフィール