4

Rails アプリケーションで google-api-ruby-client を使用して、Google ドライブとやり取りしています。フォルダー内のファイルの一覧表示、ファイルの取得、移動、コピー、削除、新しいフォルダーの作成などのすべての基本機能は正常に動作しています。

ただし、新しいファイルのアップロードは常に Timeout::Error で失敗します

アップロードするファイルを自分の Web サイト (multipart/form-data) から通常のファイル アップロードとして受け取り、これが Google ドライブにアップロードする方法です

result = nil
new_file_obj = google_drive.files.insert.request_schema.new({
  'title' => file_name,
  'mimeType' => file_mime_type,
  'parents' => [{'id' => current_folder_id}]
})

file_content = Google::APIClient::UploadIO.new(new_file.tempfile, file_mime_type, file_name)

result = google_client.execute(
    api_method: google_drive.files.insert,
    body_object: new_file_obj,
    media: file_content,
    parameters: {
      'uploadType' => 'multipart',
      'alt' => 'json'
    }
  )

new_fileクライアントがアップロードしたファイルは次のとおりです。new_file.tempfileタイプ のオブジェクトを返しTempfileます。

executeメソッドは返されず、最終的に Timeout::Error 例外が発生します。これは関連するスタック トレースです:

/lib/ruby/1.9.1/net/protocol.rb:140:in `rescue in rbuf_fill'
/lib/ruby/1.9.1/net/protocol.rb:134:in `rbuf_fill'
/lib/ruby/1.9.1/net/protocol.rb:116:in `readuntil'
/lib/ruby/1.9.1/net/protocol.rb:126:in `readline'
/lib/ruby/1.9.1/net/http.rb:2211:in `read_status_line'
/lib/ruby/1.9.1/net/http.rb:2200:in `read_new'
/lib/ruby/1.9.1/net/http.rb:1183:in `transport_request'
/lib/ruby/1.9.1/net/http.rb:1169:in `request'
/lib/ruby/1.9.1/net/http.rb:1162:in `block in request'
/lib/ruby/1.9.1/net/http.rb:627:in `start'
/lib/ruby/1.9.1/net/http.rb:1160:in `request'
/lib/ruby/gems/1.9.1/gems/faraday-0.8.4/lib/faraday/adapter/net_http.rb:74:in `perform_request'
/lib/ruby/gems/1.9.1/gems/faraday-0.8.4/lib/faraday/adapter/net_http.rb:37:in `call'
/lib/ruby/gems/1.9.1/gems/faraday-0.8.4/lib/faraday/request/url_encoded.rb:14:in `call'
/lib/ruby/gems/1.9.1/gems/google-api-client-0.5.0/lib/google/api_client/request.rb:154:in `send'
/lib/ruby/gems/1.9.1/gems/google-api-client-0.5.0/lib/google/api_client.rb:546:in `execute'

ここの例に従ってこのコードを書きました: https ://developers.google.com/drive/examples/ruby# Saving_new_files

アップロードしようとしているファイルは小さな png 画像です。ディスクに書き込むとファイルを表示できるため、ファイルは Web アプリケーションに適切に送信されます。drive.google.com からファイルをアップロードできるので、Google サーバーはダウンしていません。これは、ネットワークが十分であることも意味します。

では、タイムアウトの原因は正確には何ですか?

この同じ例外の解決策として、read_timeout を増やすことが挙げられています (http://stackoverflow.com/questions/10011387/rescue-in-rbuf-fill-timeouterror-timeouterror)。それは私がすべきことですか?もしそうなら、ここで google-api-ruby-client sdk を使用してそれを行うにはどうすればよいですか?

4

4 に答える 4

1

いくつかの簡単な実験から、一時ファイルが読み取りのために巻き戻されなかった可能性があります。一時ファイルから読み取るようにクイックスタートの例を変更したところ、エラーを再現できました。例えば:

tmp = Tempfile.new('foo')
tmp.write("hello world")

media = Google::APIClient::UploadIO.new(tmp, 'text/plain', 'foo.txt')
file = drive.files.insert.request_schema.new({
  'title' => 'My document',
  'description' => 'A test document',
  'mimeType' => 'text/plain'
})
result = client.execute(
  :api_method => drive.files.insert,
  :body_object => file,
  :media => media,
  :parameters => {
    'uploadType' => 'multipart',
    'alt' => 'json'})

これにより、約 30 秒間ハングした後に同じスタック トレースが生成されます。ただし、巻き戻しの呼び出しを追加して一時ファイルをリセットすると、問題なく動作します

tmp = Tempfile.new('foo')
tmp.write("hello world")
tmp.rewind # Reset for reading...

試してみて、問題が解決するかどうかを確認してください。

于 2012-11-30T19:24:28.867 に答える
0

https://github.com/google/google-api-ruby-client/blob/master/lib/google/api_client.rb#L532-560を見る

ファラデー接続を execute メソッドに渡すことができます。何かのようなもの

conn = Faraday.default_connection
conn.options[:timeout] = 500 

result = google_client.execute(
api_method: google_drive.files.insert,
body_object: new_file_obj,
media: file_content,
parameters: {
  'uploadType' => 'multipart',
  'alt' => 'json'
 },
connection: conn
)

これにより、Net:HTTP タイムアウトが増加します。

于 2013-04-09T14:09:30.897 に答える
0

どうやらRubyを使用してフォルダーにファイルをアップロードすることに関するGoogleのドキュメントはまだ文書化されていません。以下のように実装することを意図しています。

class DriveUpload
    def self.process
            drive_service = Google::Apis::DriveV3::DriveService.new

            drive_service.authorization = Google::Auth::ServiceAccountCredentials.make_creds(
            json_key_io: File.open('client_secret.json'),
            scope: Google::Apis::DriveV3::AUTH_DRIVE)
            meta_data = Google::Apis::DriveV3::File.new(name:'README_ONDRIVE.md',parents:["1gUxa7_9kbaBX_iofwUYKU_3BFXbBu6Ip"])

            file = drive_service.create_file(meta_data, upload_source: 'README.md',content_type: 'text/plain')

    end
end

とは、ドライブ内のフォルダー (サービス アカウントと共有したフォルダー) を意味することに注意してください。

于 2021-01-20T06:12:31.293 に答える
-1

この答えは間違っています。ファイルをアップロードするのにdrive.install許可は必要ありません。

今日drive.install、提案された@Steve Bazylなしでアップロードを試みましたが、(tmp_file.rewind呼び出しがなくても)うまくいきました。

環境内で他に何も変更されていないため、問題は一時的なものだったようです。

問題は権限が不十分であることが判明しました。以前は、これらはユーザーの許可を求めていたスコープでした:

https://www.googleapis.com/auth/userinfo.email 
https://www.googleapis.com/auth/userinfo.profile 
https://www.googleapis.com/auth/drive

Googleドライブinstalledでは、ユーザーに代わってファイルをアップロードするためのアプリケーションが必要です。また、アプリをinstalled次のスコープへのアクセス許可にするためには、次のことも要求する必要があります。https://www.googleapis.com/auth/drive.install

ソース:

  1. API を使用して Google ドライブにファイルを追加/作成/挿入するにはどうすればよいですか? (そこに記載されているように、アプリを chrome ストアにリストする必要はありません。drive.install パーミッションを要求するだけで十分です。すべてのユーザーを再認証/再承認して、新しいトークンを取得してください)

  2. https://developers.google.com/drive/scopes#google_drive_scopes

ただし、これにTimeout::Errorはまだ多少の異常があります。おそらく、Google サーバーは、提供されたトークンに不十分な権限があることを確認したときに、エラー メッセージで応答しませんでした。

PS : 誰かが を説明するとTimeout::Error、それが正解として受け入れられます。

于 2012-11-29T18:09:57.430 に答える