Ruby调用Google Drive export_file报错:不支持请求的转换
Ruby调用Google Drive API export_file方法在文件只读权限下报错:badRequest: The requested conversion is not supported
问题现象
调用Google Drive API的export_file方法时间歇性失效,get_file可以正常获取文件信息,但export_file抛出错误:
Google::Apis::ClientError: badRequest: The requested conversion is not supported
进一步排查发现:当文件设置为只读公开权限时必现错误,设置为修改公开权限时功能正常。此前该功能运行稳定,近期出现此问题。
完整代码
OOB_URI = 'urn:ietf:wg:oauth:2.0:oob' SCOPE = 'https://www.googleapis.com/auth/drive' CLIENT_SECRETS_PATH = 'private/credentials-2.json' TOKEN_PATH = 'private/tokens.yaml' USER_ID = ENV['USER'] class GoogleDriveGetFiles def call(file_name) @file_name = file_name credentials = auth drive_service = drive_service_auth(credentials) file_id = get_file(drive_service) write_in_file(file_id, drive_service) end private def auth client_id = Google::Auth::ClientId.from_file(CLIENT_SECRETS_PATH) token_store = Google::Auth::Stores::FileTokenStore.new(file: TOKEN_PATH) authorizer = Google::Auth::UserAuthorizer.new(client_id, SCOPE, token_store) credentials = authorizer.get_credentials(USER_ID) if credentials.nil? url = authorizer.get_authorization_url(base_url: OOB_URI) puts "Open #{url} in your browser and enter the resulting code:" code = gets.chomp credentials = authorizer.get_and_store_credentials_from_code( user_id: USER_ID, code: code, base_url: OOB_URI) end credentials end def drive_service_auth(credentials) drive_service = Google::Apis::DriveV3::DriveService.new drive_service.authorization = credentials drive_service end def get_file(drive_service) files = drive_service.list_files(fields: 'nextPageToken, files(id, name, mimeType)').files file_id = nil files.each do |file| if file.name == @file_name file_id = file.id puts file.name break end end file_id end def write_in_file(file_id, drive_service) # binding.pry file = drive_service.get_file(file_id) File.write("output/#{@file_name}.txt", drive_service.export_file(file_id, 'text/plain')) puts 'Succefully write in file' end end
错误栈
/home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/google-apis-core-0.11.0/lib/google/apis/core/http_command.rb:239:in `check_status': badRequest: The requested conversion is not supported. (Google::Apis::ClientError) from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/google-apis-core-0.11.0/lib/google/apis/core/api_command.rb:135:in `check_status' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/google-apis-core-0.11.0/lib/google/apis/core/http_command.rb:202:in `process_response' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/google-apis-core-0.11.0/lib/google/apis/core/http_command.rb:321:in `execute_once' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/google-apis-core-0.11.0/lib/google/apis/core/http_command.rb:126:in `block (2 levels) in do_retry' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/retriable-3.1.2/lib/retriable.rb:61:in `block in retriable' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/retriable-3.1.2/lib/retriable.rb:56:in `times' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/retriable-3.1.2/lib/retriable.rb:56:in `retriable' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/google-apis-core-0.11.0/lib/google/apis/core/http_command.rb:123:in `block in do_retry' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/retriable-3.1.2/lib/retriable.rb:61:in `block in retriable' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/retriable-3.1.2/lib/retriable.rb:56:in `times' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/retriable-3.1.2/lib/retriable.rb:56:in `retriable' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/google-apis-core-0.11.0/lib/google/apis/core/http_command.rb:113:in `do_retry' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/google-apis-core-0.11.0/lib/google/apis/core/http_command.rb:104:in `execute' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/google-apis-core-0.11.0/lib/google/apis/core/base_service.rb:418:in `execute_or_queue_command' from /home/we/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/google-apis-drive_v3-0.37.0/lib/google/apis/drive_v3/service.rb:1064:in `export_file' from /home/we/ruby/parse/google_drive_get_file.rb:64:in `write_in_file' from /home/we/ruby/parse/google_drive_get_file.rb:19:in `call' from main.ruby:10:in `<main>'
问题分析
这个错误的核心原因是Google Drive API的权限限制逻辑:即使你的OAuth令牌拥有drive完整权限,当文件本身被设置为只读公开权限时,API的导出转换操作会被限制——Google Drive的转换服务需要更高权限才能处理导出请求,仅只读权限无法触发转换流程。
解决方案
方案1:给OAuth服务账号分配文件编辑权限(推荐)
不需要设置文件为公开修改权限,只需确保你的OAuth服务账号拥有目标文件的编辑权限:
- 打开Google Drive找到目标文件,点击「分享」
- 在credentials-2.json文件中找到
client_email字段的邮箱地址 - 将该邮箱添加为文件协作者,赋予「编辑」权限
- 保存设置后重新测试
方案2:替换导出为直接下载(适用于非Google原生格式)
如果目标文件是txt、pdf等可直接下载的格式,跳过导出转换步骤,直接通过文件的下载链接获取内容:
def write_in_file(file_id, drive_service) file = drive_service.get_file(file_id, fields: 'webContentLink') require 'net/http' uri = URI(file.web_content_link) response = Net::HTTP.get_response(uri) File.write("output/#{@file_name}.txt", response.body) puts 'Successfully write in file' end
注意:Google Docs、Sheets等原生格式仍需使用export_file,但确保服务账号有编辑权限即可正常导出。
方案3:更新API依赖库
旧版本的Google API Ruby客户端可能存在权限处理bug,更新依赖库到最新版本:
bundle update google-apis-drive_v3 google-apis-core
验证步骤
- 检查OAuth令牌的权限范围是否包含
https://www.googleapis.com/auth/drive(代码中已设置,可在Google Cloud Console的OAuth consent screen中确认) - 调用API前打印文件权限信息,确认服务账号的权限类型:
def write_in_file(file_id, drive_service) file = drive_service.get_file(file_id) permissions = drive_service.list_permissions(file_id) puts permissions.permissions.inspect # 查看服务账号的权限是否为编辑权限 File.write("output/#{@file_name}.txt", drive_service.export_file(file_id, 'text/plain')) puts 'Successfully write in file' end
内容的提问来源于stack exchange,提问作者comm1ted
相关产品推荐
相关产品推荐

