4

I try to download files from a directory on Google Disk.

The code, mostly copied from official quickstart guide, works fine:

# ... code from official quickstart tutorial...

# Initialize the API
service = Google::Apis::DriveV3::DriveService.new
service.client_options.application_name = APPLICATION_NAME
service.authorization = authorize


# now the real deal
response = service.list_files(q: "'0ByJUN4GMe_2jODVJVVpmRE1VTDg' in parents and trashed != true",
                              page_size: 100,
                              fields: 'nextPageToken, files(id, name)')
puts 'Files:'
puts 'No files found' if response.files.empty?
response.files.each do |file|
  puts "#{file.name} (#{file.id})"
  # content = service.get_file(file.id, download_dest: StringIO.new)
end

The output looks fine:

Files:
k.h264 (0B4D93ILRdf51Sk40UzBoYmZKMTQ)
output_file.h264 (0B4D93ILRdf51V1RGUDFIWFQ5cG8)
test.mp4 (0B4D93ILRdf51dWpoZWdBV3l4WjQ)
test2.mp4 (0B4D93ILRdf51ZmN4ZGlwZjBvR2M)
test3.mp4 (0B4D93ILRdf51ZXo0WnVfdVBjTlk)
12.mp4 (0ByJUN4GMe_2jRzEwS1FWTnVkX00)
01.mp4 (0ByJUN4GMe_2jSlRWVEw4a1gxa2s)
01.mp4 (0ByJUN4GMe_2jOFpPMW9YNjJuY2M)

But once I uncomment content = service.get_file(file.id, download_dest: StringIO.new), I get a lot of errors:

Files:
k.h264 (0B4D93ILRdf51Sk40UzBoYmZKMTQ)
/Users/mvasin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/google-api-client-0.9.15/lib/google/apis/core/http_command.rb:211:in `check_status': Invalid request (Google::Apis::ClientError)
[...lots of other 'from' stuff...]
from /Users/mvasin/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/google-api-client-0.9.15/generated/google/apis/drive_v3/service.rb:772:in `get_file'
from quickstart.rb:56:in `block in <main>'
from quickstart.rb:54:in `each'
from quickstart.rb:54:in `<main>'

But that's the way it should work according to ruby section in "download files" official tutorial.

I also tried content = service.get_file(file.id, download_dest: "/tmp/#{file.name}"), but it failed with the same set of errors.

UPDATE: Here are my findings. If you start with Google Drive API Ruby quick start tutorial, and want make it download something,

1) change scope to not just let your script read meatadata, but read files contents as well:

SCOPE = Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY to at least SCOPE = Google::Apis::DriveV3::AUTH_DRIVE_READONLY

2) Filter out google docs files, because you can't download them this way, you have to convert them. To filer them:

2.1) Add mime_type to fileds set:

response = service.list_files(page_size: 10, fields: 'nextPageToken, files(id, name, mime_type)')

2.2) and in the final loop where you print files' ids and names, put something like

service.get_file(file.id, download_dest: "/your/path/#{file.name}") unless file.mime_type.include? "application/vnd.google-apps"

Mikhail Vasin
  • 2,421
  • 1
  • 24
  • 31
  • 1
    Do you get the same error without the `download_dest:` argument? – Nakilon Sep 25 '16 at 03:57
  • 1
    @Nakilon It gives no errors if I omit `download_dest: ...`, and `content` variable seems to be a proper instanse of `Google::Apis::DriveV3::File` class. But how do I save files? The `content.web_content_link` gives `nil` (I have changed `response = service.list_files(page_size: 10)` in order not to filter fields, but it doesn't help). – Mikhail Vasin Sep 25 '16 at 20:55

1 Answers1

3

From the error that you got, it says that your request is invalid. So make sure that your request there are correct. Here is the documentation on how to download files using Ruby(just click the Ruby on the example to view the ruby code.)

Take NOTE: Downloading the file requires the user to have at least read access. Additionally, your app must be authorized with a scope that allows reading of file content.

For more information, check these threads:

Community
  • 1
  • 1
KENdi
  • 7,576
  • 2
  • 16
  • 31
  • I increased scope to `Google::Apis::DriveV3::AUTH_DRIVE`, but it didn't help. I still have the same error. – Mikhail Vasin Sep 25 '16 at 20:49
  • 1
    http_command.rb:211 looks like this: `raise Google::Apis::ClientError.new(message, status_code: status, header: header, body: body)`. I had to debug these variables: `status` appears to be `403`, in `header` there is `Only files with binary content can be downloaded. Use Export with Google Docs files.` It just happened that I had some google docs files now in the folder, and they threw the error. A very uninformative error. Now it's OK! – Mikhail Vasin Sep 25 '16 at 22:01