You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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服务账号拥有目标文件的编辑权限:

  1. 打开Google Drive找到目标文件,点击「分享」
  2. 在credentials-2.json文件中找到client_email字段的邮箱地址
  3. 将该邮箱添加为文件协作者,赋予「编辑」权限
  4. 保存设置后重新测试

方案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

验证步骤

  1. 检查OAuth令牌的权限范围是否包含https://www.googleapis.com/auth/drive(代码中已设置,可在Google Cloud Console的OAuth consent screen中确认)
  2. 调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:25:07