Google Apps Script (スプレッドシート) で生成されたファイルを Ruby 経由でダウンロードする
概要
Google スプレッドシートの各タブに基づいて json ファイルを生成する次の Apps Script について考えてみましょう。
function makeJSON() {
var spreadsheetId = 'someId';
var spreadsheet = SpreadsheetApp.openById(spreadsheetId);
var sheets = spreadsheet.getSheets();
var urls = []; // Array to store the URLs of the created files
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++) {
//process data in the sheets
return obj;
});
var json = JSON.stringify(objects, null, 2);
// Create a blob from the JSON string
var blob = Utilities.newBlob(json, 'application/json', sheet.getName() + '.json');
var folder = DriveApp.getFolderById('someId');
var file = folder.createFile(blob);
file.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
urls.push(file.getUrl());
}
}
function doGet() {
var urls = makeJSON(); // Call the function to generate JSON files and get their URLs
Logger.log(urls) //this logs all the files correctly
return ContentService.createTextOutput(JSON.stringify({urls: urls})).setMimeType(ContentService.MimeType.JSON);
}
folder.createFile(blob); を使用してすべての json ファイルを Google ドライブにダウンロードすると、正常に動作します。ただし、スクリプトを手動で実行してファイルをダウンロードする必要がないように、Ruby スクリプトを使用してこれを実行しようとしています。そこで、それを Web アプリ (パブリック権限) としてデプロイし、それを以下の web_app_url に置きました。 .rb ファイルは次のとおりです。
require 'typhoeus'
require 'json'
web_app_url = 'https://script.google.com/macros/s/digits/exec'
download_directory = './downloads'
# Make an HTTP GET request to trigger the Web App
response = Typhoeus.get(web_app_url, followlocation: true)
if response.success?
json_response = JSON.parse(response.body)
json_urls = json_response['urls']
# Download each file to the specified directory
json_urls.each do |url|
file_name = File.basename(url)
download_path = File.join(download_directory, file_name)
# Use open-uri to open the URL and download the file
require 'open-uri'
open(url, 'rb') do |file|
File.open(download_path, 'wb') do |local_file|
local_file.write(file.read)
end
end
puts "Downloaded #{file_name} to #{download_directory}"
end
else
puts "HTTP status code: #{response.code}"
puts "Response body: #{response.body}"
puts "Failed to fetch URLs: #{response.status_message}"
end
しかし、次のエラーが発生します。
warning: calling URI.open via Kernel#open is deprecated, call URI.open directly or use URI#open
Traceback (most recent call last):
9: from download.rb:15:in `<main>'
8: from download.rb:15:in `each'
7: from download.rb:21:in `block in <main>'
6: from /Users/me/.rvm/rubies/ruby-2.7.2/lib/ruby/2.7.0/open-uri.rb:19:in `open'
5: from /Users/me/.rvm/rubies/ruby-2.7.2/lib/ruby/2.7.0/open-uri.rb:50:in `open'
4: from /Users/me/.rvm/rubies/ruby-2.7.2/lib/ruby/2.7.0/open-uri.rb:744:in `open'
3: from /Users/me/.rvm/rubies/ruby-2.7.2/lib/ruby/2.7.0/open-uri.rb:178:in `open_uri'
2: from download.rb:22:in `block (2 levels) in <main>'
1: from download.rb:22:in `open'
download.rb:22:in `initialize': No such file or directory @ rb_sysopen - ./downloads/view?usp=drivesdk (Errno::ENOENT)
どこが間違っているのか誰か教えてもらえますか?また、これらのファイルをマシン上のどこにダウンロードするかを指定するにはどうすればよいでしょうか?
解決策
表示されているスクリプトから、 Logger.log(urls) // これによりすべてのファイルが正しく記録されると思うと、現在の問題の原因は urls.push(file.getUrl()) の getUrl() にあるのではないかと推測しました。 ;。 getUrl() の場合、URL は https://drive.google.com/file/d//view?usp=drivesdk のようになります。このリンクはファイルへの直接リンクではありません。これが現在の問題の原因である可能性があると思います。私の推測が正しければ、次の修正はどうでしょうか?
この変更では、Ruby 側が変更されます。
json_urls.each do |url|
file_name = File.basename(url)
json_urls.each do |url|
id = url.split("/")[5]
url = "https://drive.usercontent.google.com/download?confirm=xxx&id=#{id}" # This is from https://gist.github.com/tanaikech/f0f2d122e05bf5f971611258c22c110f
file_name = File.basename(url)
変更したスクリプト全体は以下の通りです。
require 'typhoeus'
require 'json'
web_app_url = 'https://script.google.com/macros/s/{deploymentId}/exec'
download_directory = './downloads'
# Make an HTTP GET request to trigger the Web App
response = Typhoeus.get(web_app_url, followlocation: true)
if response.success?
json_response = JSON.parse(response.body)
json_urls = json_response['urls']
# Download each file to the specified directory
json_urls.each do |url|
id = url.split("/")[5]
url = "https://drive.usercontent.google.com/download?confirm=xxx&id=#{id}"
file_name = File.basename(url)
download_path = File.join(download_directory, file_name)
# Use open-uri to open the URL and download the file
require 'open-uri'
open(url, 'rb') do |file|
File.open(download_path, 'wb') do |local_file|
local_file.write(file.read)
end
end
puts "Downloaded #{file_name} to #{download_directory}"
end
else
puts "HTTP status code: #{response.code}"
puts "Response body: #{response.body}"
puts "Failed to fetch URLs: #{response.status_message}"
end