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

如何向Google Apps Script Web应用传递不可序列化的JavaScript对象

解决方案

问题根因

所有通过UrlFetchApp传递到Apps Script Web App的参数都会被自动序列化为字符串,绑定脚本执行上下文的原生对象(Lock、File、Blob等)无法跨脚本实例传递,你遇到的报错均是因为传递后的参数已经丢失了原对象的所有方法和二进制内容,仅保留了纯文本描述。

具体错误说明

  1. ScriptLock传递失效:Lock实例仅在当前脚本执行上下文生效,序列化后仅为普通字符串,自然不存在releaseLock方法。且跨脚本的Lock本身不具备锁效力,不需要传递。
  2. 附件参数无效:File/Blob对象序列化后仅保留类名和ID信息,无实际二进制内容,无法被GmailApp识别为合法附件。
  3. 转Blob后无附件:直接将Blob放入payload会被自动转为toString()的文本结果,二进制内容完全丢失,因此邮件能发送但无附件。

修复方案(推荐:传文件ID,实现最简单)

核心逻辑调整

  • 锁直接在调用端申请,等Web App请求返回后再释放,不需要传递给Web App
  • 仅传递文件ID给Web App,由具备权限的Web App直接从Drive读取文件生成附件

修改后的代码

客户端 gs

function testEmail() {
  var attachmentFileId = "file id"; // 仅传递文件ID
  var emailBody = 'email body content';
  sendEmailFromClient('sendTo@example.com', "test", emailBody, attachmentFileId, 'replyTo@example.com');
}

function sendEmailFromClient(sendTo, title, body, attachmentFileId, replyTo) {
  var scriptLock = LockService.getScriptLock();
  if(!scriptLock.tryLock(8000)){
    return;
  }
  try {
    var formData = {
      'sendTo': sendTo,
      'title': title,
      'body' : body,
      'attachmentFileId': attachmentFileId,
      'replyTo' : replyTo
    };
    var options = {
      'method': 'post',
      'payload': formData
    };
    Logger.log(UrlFetchApp.fetch('web app url', options).getContentText());
  } finally {
    // 锁在当前上下文申请,就在当前上下文释放
    scriptLock.releaseLock();
  }
}

Web App gs

function doPost(event) {
  var p = event.parameter;
  try {
    // 由具备权限的Web App读取文件生成附件
    var attachment = DriveApp.getFileById(p.attachmentFileId).getBlob();
    var result = Library['sendEmail'](p.sendTo, p.title, p.body, [attachment], p.replyTo);
    return ContentService.createTextOutput(result);
  } catch (error) {
    Library.troubleshooting(error);
    return ContentService.createTextOutput(error.toString());
  }
}

Library gs 修正版

function sendEmail(sendTo, title, body, attachments, replyTo) {
  // 替换为你实际的全局配置值
  const gv_accountingEmail = "默认回复邮箱";
  const gv_systemBrandName = "系统发件名称";
  replyTo = replyTo || gv_accountingEmail;
  attachments = attachments || [];
  try {
    GmailApp.sendEmail(
      sendTo, // 修正原代码中无意义的sendTo.valid调用
      title,
      "html content only",
      {
        attachments: attachments,
        replyTo: replyTo,
        name: gv_systemBrandName,
        htmlBody: body
      }
    );
    return true;
  } catch (error) {
    return error.toString();
  }
}

备选方案:Web App无权限访问用户Drive时用Base64传附件

如果Web App的执行身份没有权限读取用户的Drive文件,可以把附件转成Base64编码传递:

客户端新增Blob转Base64逻辑

// 客户端获取blob后转base64,同时传递mimeType和文件名
var blob = DriveApp.getFileById("file id").getBlob();
var formData = {
  // 其他参数不变
  'blobBase64': Utilities.base64Encode(blob.getBytes()),
  'blobName': blob.getName(),
  'blobType': blob.getContentType()
}

Web App端还原Blob

var attachment = Utilities.newBlob(
  Utilities.base64Decode(p.blobBase64),
  p.blobType,
  p.blobName
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 21:45:00