【问题标题】:Google app script can not insert image to spreadsheet sometimes谷歌应用脚​​本有时无法将图像插入电子表格
【发布时间】:2020-04-06 06:30:47
【问题描述】:

我的项目是由 Ruby on Rails 编写的,因为 google-api-client gem 不支持通过 sheet api 将图像插入电子表格,所以我使用 Google 应用脚本来处理这个任务。大多数情况下,此调用的插入已成功:

@app_script.run_script(script_id, request) 

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

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

错误详情:[{\"@type\"=>\"type.googleapis.com/google.apps.script.v1.ExecutionError\", \"scriptStackTraceElements\"=>[{\"function\" =>\"addImageOnSpreadsheet\"}], \"errorMessage\"=>\"异常:从 URL 或错误 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 信息:完成 错误:3" "错误详情:[{\"@type\"=>\"type.googleapis.com/google.apps.script.v1.ExecutionError\", \"scriptStackTraceElements\"=>[{\"function\"=> \"addImageOnSpreadsheet\"}], \"errorMessage\"=>\"异常:从 URL 或错误 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 信息:完成 “插入图像错误:#,#” “错误:3” "错误详情:[{\"@type\"=>\"type.googleapis.com/google.apps.script.v1.ExecutionError\", \"scriptStackTraceElements\"=>[{\"function\"=> \"addImageOnSpreadsheet\"}], \"errorMessage\"=>\"异常:从 URL 或错误 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 信息:完成

问题似乎发生在 url 图片上,不知何故 google app 脚本无法提取图片数据。但是当出现问题时,我只需将错误日志中的上述图像网址手动复制并粘贴到浏览器,它就可以成功下载图像。 请注意,我已经为图片 url 设置了 public。

以下是我的谷歌应用脚​​本部分:

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

有人有这方面的经验吗?

【问题讨论】:

  • 您能否提供示例 URL 以复制您的问题?或者,如果您在脚本编辑器中直接使用 Google Apps Script 中的 URL 时没有出现错误,您能否提供请求正文或您的脚本?
  • @Tanaike 我刚刚将它们附加到问题中。
  • 感谢您的回复和补充信息。首先,从您的回复来看,当您直接在 Google Apps 脚本中使用该 URL 时,不会发生错误。我的理解正确吗?而且,对于 webContentLink,文件需要公开共享。你能确认吗?并且,您能确认该文件是否是可以放入的图像文件吗?此外,当您将文件 ID 作为参数并通过在脚本中检索来使用图像 blob 时,您会得到什么结果?如果这些没有导致解决方案或问题的原因,我很抱歉。
  • 感谢您的建议,我的意思是当脚本执行错误时,如果我将图像URL手动复制并粘贴到Web浏览器,我仍然可以看到浏览器可以很好地下载图像。正如我所说,我已经为我的图像文件夹设置了网络上的公共权限。这意味着所有图像都是公开的。然后我还尝试修改我的应用程序脚本和参数以通过 webContentLink 检索图像 url,我观察到相同的错误日志。可以在这里找到:script.google.com/d/…
  • 我尝试运行我的应用程序几次,有时它可以完成插入而没有任何错误。有时,会发生上述错误。

标签: ruby-on-rails google-apps-script google-sheets google-apps-script-api


【解决方案1】:

这是我的理解:

  • 在您的情况下,将图像插入 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: ###},
        ,
        ,
      ];
    

【讨论】:

  • 谢谢,这就是我想要的。但是在使用你的库时,我面临另一个错误:Error detail: [{\"@type\"=>\"type.googleapis.com/google.apps.script.v1.ExecutionError\", \"scriptStackTraceElements\"=>[{\"function\"=>\"ImgApp.DoResize\", \"lineNumber\"=>125}, {\"function\"=>\"doResize\", \"lineNumber\"=>37}], \"errorMessage\"=>\"Error: '1046l265YJSBDhMiW19t-lz7QCLZeVUUT' is not compatible file. Error message is {}\", \"errorType\"=>\"ScriptError\"}]"。它可能来自您的 doResize 函数吗?
  • @Tiktac 感谢您的回复。我带来的不便表示歉意。关于1046l265YJSBDhMiW19t-lz7QCLZeVUUT的文件,能问一下它的文件类型吗?如果是 BMP、GIF、PNG 和 JPG 以外的文件,则可能会发生错误。请注意这一点。
  • 它们是 jpg 图像,我想插入。你可以在这里看到这个文件drive.google.com/file/d/1046l265YJSBDhMiW19t-lz7QCLZeVUUT/view
  • @Tiktac 感谢您的回复。当我测试 URL 的图像时,没有发生错误。那么您可以再次确认脚本并请求正文吗?而当你直接在脚本编辑器运行脚本时,你会得到什么结果?
  • @Tiktac 感谢您的回复。例如,在您的情况下,如何使用请求正文中的数组通过一个 API 调用发送多个文件 ID?并且文件 ID 在 Google Apps 脚本中处理。在您的 ruby​​ 脚本中,parameters[@sheet_id, @sheet_name, url_image, start_col, start_row, width, height] 是数组中的元素之一。这个怎么样?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-15
相关资源
最近更新 更多