Google 应用程序脚本有时无法将图像插入电子表格

Google app script can not insert image to spreadsheet sometimes

我的项目是Ruby在Rails上写的,因为google-api-client gem不支持插入图片传播sheet 到 sheet apis,所以我正在使用 Google 应用程序脚本来处理此任务。大多数情况下,插入已成功通过此调用:

@app_script.run_script(script_id, request) 

我只是为所有好奇的人提供我的脚本: https://script.google.com/a/vectorgroup.vn/d/1ndcgpfJMj3YdKj0pEvHWz0pF4NtcQyR1Qg8wj7ZnpKfIwP2UsH0xaYq4/edit?splash=yes

问题是有时调用失败并出现以下错误:

Error detail: [{\"@type\"=>\"type.googleapis.com/google.apps.script.v1.ExecutionError\", \"scriptStackTraceElements\"=>[{\"function\"=>\"addImageOnSpreadsheet\"}], \"errorMessage\"=>\"Exception: Error retrieving image from URL or bad URL: https://drive.google.com/uc?id=1MS6KMfua7kZCSGMUhny4kDUvalxTkoKJ&export=download\", \"errorType\"=>\"ScriptError\"}]" 2020-04-06T06:03:33.821Z pid=26645 tid=tz8bh class=ImageTakerWorker jid=d847bf91beea8aeb4a30b042 elapsed=11.689 INFO: done Error: 3" "Error detail: [{\"@type\"=>\"type.googleapis.com/google.apps.script.v1.ExecutionError\", \"scriptStackTraceElements\"=>[{\"function\"=>\"addImageOnSpreadsheet\"}], \"errorMessage\"=>\"Exception: Error retrieving image from URL or bad URL: https://drive.google.com/uc?id=1G9EDgvygwVztMG66FArZ6BEFpzW71izA&export=download\", \"errorType\"=>\"ScriptError\"}]" 2020-04-06T08:00:28.330Z pid=26645 tid=tz7zl class=ImageTakerWorker jid=a6b4fcb47db15f71dbf1d3f5 elapsed=6.514 INFO: done "Insert image ERROR: #, #" "Error: 3" "Error detail: [{\"@type\"=>\"type.googleapis.com/google.apps.script.v1.ExecutionError\", \"scriptStackTraceElements\"=>[{\"function\"=>\"addImageOnSpreadsheet\"}], \"errorMessage\"=>\"Exception: Error retrieving image from URL or bad URL: https://drive.google.com/uc?id=1_3KzBDDgpINMCNkEZj2LivqdUaxFKZNT&export=download\", \"errorType\"=>\"ScriptError\"}]" 2020-04-06T08:00:28.941Z pid=26645 tid=tzahx class=ImageTakerWorker jid=8010f8c64cb9a0efa672b713 elapsed=7.121 INFO: done

问题似乎发生在 url 图像上,不知何故 google 应用程序脚本无法提取图像数据。但是当问题发生时,我只是将上面的图像 url 手动复制并粘贴到浏览器的错误日志中,它可以成功下载图像。 请注意,我已经为图像 url.

设置了 public

下面是我的 google 应用程序脚本部分:

class GoogleAppScript
  APPLICATION_NAME = "Insert image to spreadsheet".freeze

  def initialize(user_id, sheet_id, options = {})
    @user = User.find(user_id)
    @sheet_id = sheet_id
    @from_class = options[:from_class]
    @service = options[:service]
    @keyword = options[:keyword]
    @sheet_name = options[:service] == "google" ? "G" + options[:keyword].strip : "Y" + options[:keyword].strip
    @image_file_id = options[:image_file_id]
    @google_authorization = GoogleAuthorization.new(@user).authorize
    @app_script = Google::Apis::ScriptV1::ScriptService.new
    @app_script.client_options.application_name = APPLICATION_NAME
    @app_script.authorization = @google_authorization
  end

  def execute
    script_id = "1ndcgpfJMj3YdKj0pEvHWz0pF4NtcQyR1Qg8wj7ZnpKfIwP2UsH0xaYq4"
    url_image = "https://drive.google.com/uc?id=#{@image_file_id}&export=download"

    start_col = 1
    if @from_class == "ImageX"
      start_row = 51
      width = 692
      height = 1500
    else # "ImageY"
      start_row = @keyword.last == " " ? 30 : 9
      width = 694
      height = 418
    end
    request = Google::Apis::ScriptV1::ExecutionRequest.new(
      function: "addImageOnSpreadsheet",
      parameters: [@sheet_id, @sheet_name, url_image, start_col, start_row, width, height],
    )

    begin
      response = @app_script.run_script(script_id, request)
      if response.error
        # Retry until success
        # ImageTakerWorker.perform_async(@user.id, @sheet_id, @sheet_name, @image_file_id)
        p "Insert image ERROR: #{response}, #{response.error}"
        p "Error: #{response.error.code}"
        p "Error detail: #{response.error.details}"
      else
        p "Insert image successfully"
      end
    rescue Google::Apis::ClientError
      # Handle the error...
    end
  end
end

有人对此有经验吗?

这是我的理解:

  • 在您的情况下,将图像插入 Google 电子表格时,会出现 Server error 错误。
  • 在这种情况下,认为图像的大小超过了限制。 Reference
  • 您想在插入到 Google 电子表格的限制大小超过时调整图像大小。

问题和解决方法:

在这种情况下,即使使用setWidthsetHeight,也无法消除错误。因为插入图片时出现错误。所以在这个答案中,我想建议通过在 Google Apps 脚本库中调整大小来插入图像。

修改后的脚本:

当你的脚本修改后,变成如下。在使用此脚本之前,请先安装 a GAS library of ImgApp.

function addImageOnSpreadsheet(spreadsheet_id, sheet_name, image_file_id, column, row, width, height) {
  let blobSource = DriveApp.getFileById(image_file_id).getBlob();
  const obj = ImgApp.getSize(blobSource);
  if (obj.height * obj.width > 1048576) {
    blobSource = ImgApp.doResize(image_file_id, width).blob;
  }
  let image = SpreadsheetApp.openById(spreadsheet_id).insertImage(blobSource, column, row);
  image.setWidth(width).setHeight(height);
}
  • 作为测试,我建议直接在脚本编辑器中运行脚本。

注:

  • 在本例中,使用了以下3个作用域。尽管我不确定您的整个脚本,但请添加这些范围。请注意这一点。在您的情况下,请添加范围并重新授权。这样,就可以使用有效的访问令牌。
    • https://www.googleapis.com/auth/drive
    • https://www.googleapis.com/auth/script.external_request
    • https://www.googleapis.com/auth/spreadsheets

参考文献:

已添加:

示例脚本:

此示例脚本用于接收多个文件 ID。

function addImageOnSpreadsheet(ar) {
  ar.forEach(o => {
    let blobSource = DriveApp.getFileById(o.image_file_id).getBlob();
    const obj = ImgApp.getSize(blobSource);
    if (obj.height * obj.width > 1048576) {
      blobSource = ImgApp.doResize(o.image_file_id, o.width).blob;
    }
    var image = SpreadsheetApp.openById(o.spreadsheet_id).insertImage(blobSource, o.column, o.row);
    image.setWidth(o.width).setHeight(o.height);
  });
}
  • 例如ar如下

      ar = [
        {spreadsheet_id: "###", image_file_id: "###", column: ##, row: ##, width: ###, height: ###},
        {spreadsheet_id: "###", image_file_id: "###", column: ##, row: ##, width: ###, height: ###},
        ,
        ,
      ];