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

如何通过Google脚本更新Google Drive文件版本并保留共享链接?

需求与问题

我已经能通过Google Apps Script的setContent()方法提取邮件数据并更新Google Drive文件内容,但实际需求是将邮件中的完整附件替换为Drive中现有文件的新版本——这样既能保持原文件的共享链接不变,又能让文件内容更新到最新版本。

现有代码

目前实现setContent更新的代码如下:

function UploadToDrive() {
  var labelName = "Port"; // Gmail中设置的标签
  var targetFolderName = "Schedules"; // Google Drive中的目标文件夹名
  var targetFileName = "Schedule.xlsx"; // 目标文件夹中的目标文件名

  // 获取带指定标签的所有邮件线程
  var label = GmailApp.getUserLabelByName(labelName);
  var threads = label.getThreads();
  if (threads.length > 0) {
    // 获取最新的邮件线程
    var mostRecentThread = threads[0];

    // 获取该线程中最新的邮件
    var messages = mostRecentThread.getMessages();
    var latestMessage = messages[messages.length - 1];

    // 检查最新邮件中的附件
    var attachments = latestMessage.getAttachments();

    for (var k = 0; k < attachments.length; k++) {
      var attachment = attachments[k];
      var attachmentName = attachment.getName().toLowerCase();

      // 检查附件名是否包含指定关键词
      if (attachmentName.includes("Work Schedule".toLowerCase())) {
          var targetFolder = DriveApp.getFoldersByName(targetFolderName).next();
          var targetFile = targetFolder.getFilesByName(targetFileName);

          if (targetFile.hasNext()){
            var file = targetFile.next();
            file.setContent(attachment.setDataFromString())
          }
      }
    }
  }
}

尝试的Drive API方法及报错

我尝试调用Drive API来实现版本更新,但代码无法正常运行,报错信息:Exception: Unexpected error while getting the method or property update on object Apiary.drive.files.

尝试的方法代码如下:

// 更新指定文件夹中目标文件版本的函数
function updateTargetFileVersion(attachment, targetFolder, targetFileName) {
  var targetFiles = targetFolder.getFilesByName(targetFileName);

  if (targetFiles.hasNext()) {
    // 如果同名文件存在,更新其版本
    var targetFile = targetFiles.next();

     // 将附件内容转为Blob
    var newContentBlob = Utilities.newBlob(attachment.getContentType(), attachment.getDataAsString());

    // 上传新内容创建新版本
    var updatedFile = Drive.Files.update({}, targetFile.getId(), newContentBlob);

    // 确保文件名正确
    updatedFile.setName(targetFileName);
  } 
}

解决方案

问题分析

  1. 原setContent()方法仅适用于纯文本文件,对于Excel这类二进制文件会损坏内容,无法正常打开。
  2. 调用Drive API报错的核心原因:
    • 未在脚本中启用Drive API服务;
    • Utilities.newBlob的参数顺序错误(正确顺序为内容, 内容类型, 文件名);
    • Drive.Files.update的调用格式不符合API要求。

修正后的最优代码(无需Drive API)

DriveApp本身提供了setBlob()方法,可直接将附件的二进制内容更新到现有文件,自动创建新版本且保留原共享链接,无需额外启用API:

function UploadToDrive() {
  var labelName = "Port"; // Gmail中设置的标签
  var targetFolderName = "Schedules"; // Google Drive中的目标文件夹名
  var targetFileName = "Schedule.xlsx"; // 目标文件夹中的目标文件名

  var label = GmailApp.getUserLabelByName(labelName);
  var threads = label.getThreads();
  if (threads.length === 0) return;

  // 获取最新线程的最新邮件
  var mostRecentThread = threads[0];
  var latestMessage = mostRecentThread.getMessages().pop();
  var attachments = latestMessage.getAttachments();

  // 遍历附件寻找目标文件
  for (var attachment of attachments) {
    var attachmentName = attachment.getName().toLowerCase();
    if (attachmentName.includes("work schedule")) {
      var targetFolder = DriveApp.getFoldersByName(targetFolderName).next();
      var targetFiles = targetFolder.getFilesByName(targetFileName);
      
      if (targetFiles.hasNext()) {
        var targetFile = targetFiles.next();
        // 直接用附件Blob更新文件,自动创建新版本,共享链接保持有效
        targetFile.setBlob(attachment);
        // 可选:标记邮件为已读并移除标签,避免重复处理
        mostRecentThread.markRead();
        label.removeFromThread(mostRecentThread);
        break; // 找到目标附件后停止遍历
      }
    }
  }
}

若需使用Drive API的修正方案

如果需要更精细的版本控制(如设置版本描述),可启用Drive API后使用以下代码:

  1. 先在脚本编辑器中启用Drive API:点击服务 > 添加服务 > 选择Drive API并保存。
  2. 修正后的方法代码:
function updateTargetFileVersion(attachment, targetFolder, targetFileName) {
  var targetFiles = targetFolder.getFilesByName(targetFileName);
  if (!targetFiles.hasNext()) return;

  var targetFile = targetFiles.next();
  // 正确创建Blob:参数顺序为 内容, 内容类型, 文件名
  var newContentBlob = Utilities.newBlob(attachment.getDataAsString(), attachment.getContentType(), attachment.getName());
  
  // 调用Drive API更新文件,指定元数据保持文件名不变
  var updatedFile = Drive.Files.update(
    { title: targetFileName },
    targetFile.getId(),
    newContentBlob,
    { convert: false } // 禁止自动转换格式,保留原文件类型
  );
}

关键注意事项

  • 对于二进制文件(Excel、PDF、图片等),绝对不能使用setContent(),必须用setBlob()或Drive API的二进制上传方式,否则文件会损坏。
  • 处理完邮件后建议标记已读或移除标签,避免脚本重复执行时重复更新文件。

内容的提问来源于stack exchange,提问作者apex

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 07:27:12