使用Ruby下载Google Apps Script生成的Sheet JSON文件出错求助
问题分析与解决
错误原因拆解
你遇到的两个问题根源如下:
- 文件路径错误:
- 未提前创建
./downloads目录,导致写入文件时提示路径不存在 - Google Drive的
file.getUrl()返回的是文件预览页面URL(如https://drive.google.com/file/d/xxx/view?usp=drivesdk),不是直接下载链接;用File.basename(url)提取文件名时,会把view?usp=drivesdk当成文件名,这不仅不是正确的JSON文件名,还包含特殊字符,导致路径无效。
- 未提前创建
- 弃用警告:Ruby 2.7+中
Kernel#open调用URI已被弃用,需改用URI.open直接调用。 - 隐藏问题:你的Google Apps Script中
makeJSON函数没有返回urls数组,导致Web App返回的JSON中urls字段实际为undefined(你看到的Logger.log可能是在makeJSON内部,而非doGet中的urls变量)。
修复方案
1. 修改Google Apps Script代码
主要调整两点:返回直接下载链接+正确文件名,以及确保函数有返回值:
function makeJSON() { var spreadsheetId = 'someId'; var spreadsheet = SpreadsheetApp.openById(spreadsheetId); var sheets = spreadsheet.getSheets(); var fileInfos = []; // 存储下载链接和文件名的对象数组 for (var i = 1; i < sheets.length; i++) { var sheet = sheets[i]; var data = sheet.getRange(3, 1, sheet.getLastRow() - 2, sheet.getLastColumn()).getValues(); var headers = sheet.getRange(2, 1, 1, sheet.getLastColumn()).getValues()[0]; var objects = data.map(function(row) { var obj = {}; for (var j = 0; j < headers.length; j++) { obj[headers[j]] = row[j]; // 补充数据处理逻辑 } return obj; }); var json = JSON.stringify(objects, null, 2); var filename = sheet.getName() + '.json'; var blob = Utilities.newBlob(json, 'application/json', filename); var folder = DriveApp.getFolderById('someId'); var file = folder.createFile(blob); file.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW); // 构造Drive直接下载链接 var downloadUrl = "https://drive.google.com/uc?export=download&id=" + file.getId(); // 存入文件信息 fileInfos.push({url: downloadUrl, filename: filename}); } return fileInfos; // 必须返回数据给doGet } function doGet() { var fileInfos = makeJSON(); Logger.log(fileInfos); return ContentService.createTextOutput(JSON.stringify({files: fileInfos})).setMimeType(ContentService.MimeType.JSON); }
2. 修改Ruby脚本代码
修复目录创建、弃用警告、文件名获取问题:
require 'typhoeus' require 'json' require 'uri' require 'open-uri' web_app_url = 'https://script.google.com/macros/s/digits/exec' download_directory = './downloads' # 提前创建下载目录,不存在则创建 Dir.mkdir(download_directory) unless Dir.exist?(download_directory) # 请求Web App获取文件信息 response = Typhoeus.get(web_app_url, followlocation: true) if response.success? json_response = JSON.parse(response.body) file_infos = json_response['files'] file_infos.each do |info| url = info['url'] filename = info['filename'] download_path = File.join(download_directory, filename) # 使用URI.open替代弃用的Kernel#open URI.open(url, 'rb') do |remote_file| File.open(download_path, 'wb') do |local_file| local_file.write(remote_file.read) end end puts "已下载 #{filename} 到 #{download_directory}" end else puts "HTTP状态码: #{response.code}" puts "响应内容: #{response.body}" puts "获取URL失败: #{response.status_message}" end
关键修改说明
- GAS端:用文件ID构造直接下载链接,同时返回文件名,避免Ruby端解析URL出错;补充
makeJSON的返回语句,确保Web App能输出有效JSON。 - Ruby端:提前创建下载目录,解决路径不存在问题;改用
URI.open消除弃用警告;直接从GAS返回的JSON中获取文件名,保证文件名正确。
内容的提问来源于stack exchange,提问作者soleil
相关产品推荐
相关产品推荐

