ruby-on-rails - Ruby:使用 google-api-ruby-client SDK 将文件上传到 Google 驱动器失败并出现 Timeout::Error

标签 ruby-on-rails ruby file-upload google-drive-api google-api-ruby-client

我在 Rails 应用程序中使用 google-api-ruby-client 与 Google Drive 交互。列出文件夹中的文件、获取、移动、复制和删除文件、创建新文件夹等所有基本功能都运行良好。

但是上传新文件总是失败并出现 Timeout::Error

我从我的网站 (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 应用程序,因为如果我将它写入磁盘,我可以查看该文件。 Google 服务器绝对没有宕机,因为我可以从 drive.google.com 上传文件。这也意味着我的网络足够好。

那么到底是什么导致了超时呢?

针对同一异常的解决方案被提及为增加 read_timeout (http://stackoverflow.com/questions/10011387/rescue-in-rbuf-fill-timeouterror-timeouterror)。那是我应该做的吗?如果是这样,我如何使用 google-api-ruby-client sdk 在此处执行此操作?

最佳答案

从一些快速实验来看,可能只是临时文件没有倒回读取。我修改了快速入门示例以从临时文件读取并且能够重现错误。例如:

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...

试一试,看看它是否能解决您的问题。

关于ruby-on-rails - Ruby:使用 google-api-ruby-client SDK 将文件上传到 Google 驱动器失败并出现 Timeout::Error,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13603057/

相关文章:

ruby-on-rails - 如何测试 rspec shoulda 以在 Rails 中进行自定义验证?

ruby-on-rails - 从数组中删除空白元素

ruby-on-rails - Google Cloud Ruby : Error Response: [13] Timed out when starting VMs. 应用程序代码可能不健康。

ruby - 在Ruby中,如果你将一个函数赋值给一个变量,为什么它会自动运行?

jQuery 绑定(bind)到 asp.net 中的一个文件上传控件

java - 无法从新上传的 Excel 文件中读取数据

angularjs - Protractor - 如何在测试用例中使用 ng-file-upload 上传文件而不更改代码?

ruby-on-rails - 在应用程序布局中部分渲染问题(Rails)

Windows7 x86 中的 Mysql 和 Ruby on Rails 配置

ruby-on-rails - 我遇到这个问题 : undefined method `each' for #<User:0xa8dc8b8>