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

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



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


まずはじめに、oauth認証、client_id、client_secretの扱い方についてはこのページをご参照ください。

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


上記のページで紹介している認証さえ出来れば後は簡単です!



Google Drive(docs)からファイルをコピーする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

# file_idをtitleという名前でfolder_idにコピーする
def copy_file(client, drive, file_id, folder_id)
  file = drive.files.insert.request_schema.new({
    'title' => 'new_title',
    'parents' => [{:id => folder_id}]
  })

  result = client.execute(
    :api_method => drive.files.copy,
    :body_object => file,
    :parameters => {
      'fileId' => file_id,
      'alt' => 'json'})

  #jj result.data.to_hash
  result.data
end

if __FILE__ == $0
  file_format_bug_fix(CREDENTIAL_STORE_FILE)
  client, drive = setup()
  file = copy_file(client, drive, 'aaabbbccc', '111222333')
end

上記のrubyコードでは、「file_idで指定したファイルを、folder_idで指定したフォルダに、titleというファイル名でコピー」という処理をしています。APIの仕様は公式リファレンスをご参照ください。

drive.files.copyのリファレンス



その他注意事項

上記の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サイトをいくつか作っています。
著者プロフィール