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

nodemailer分块发送超大附件时如何匹配pdfBuffer与分块附件数组

nodemailer附件分块后Buffer匹配逻辑失效排查

业务背景

  • 基于nodemailer实现邮件发送能力,设置附件总大小阈值LIMIT_ATTACHMENTS:发送前计算所有附件总大小,超阈值时调用lodash_.chunk方法拆分附件为多个子块,分多封邮件发送,每封邮件保留相同主题、正文,仅携带对应分块内的附件。
  • 附件拆分前执行prepareAttachments方法:接口拉取数据生成PDF Buffer,组装为邮件附件的content字段,同时将原始BufferXSolicitudDTO格式数组赋值给类属性,供后续匹配逻辑使用。
  • 预期逻辑:每个附件分块处理时,匹配当前分块内附件对应的原始PDF Buffer与类属性存储的原始数组元素的pdfBuffer字段,两者一致时执行预设业务操作。
  • 异常现象:判断逻辑if (element.pdfBuffer === attachmentMap)始终无法进入相等分支。

问题根因

  1. 比较对象类型完全不匹配
    代码中attachmentMap是通过attachment.map(element => element.content)生成的Buffer实例数组,但判断逻辑拿单个原始DTO元素的pdfBuffer(单个Buffer实例)和整个数组做===比较,数据类型不一致,永远不可能返回true。
  2. Buffer比较方式错误
    JavaScript中===对引用类型(包括Buffer、对象、数组)的比较规则是校验内存引用地址,就算两个Buffer的二进制内容完全一致,只要不是同一个内存引用,===比较结果永远为false。
  3. 属性名拼写笔误
    prepareAttachments方法中给原始DTO数组赋值的属性是this.getCantidad,但后续匹配逻辑读取的是this.getAmount,赋值和读取的不是同一个属性,就算比较逻辑写对也拿不到原始数据。
  4. 附件拆分逻辑参数错误(附带问题)
    _.chunk方法第二个参数是每个子块的元素个数,但代码中传入的chunkSplit是计算出来的预期拆分块数,会导致拆分后的子块附件大小仍然可能超过阈值,不符合大小管控的设计目标。

修复方案

  1. 统一类属性命名,修正拼写错误,确保prepareAttachments赋值和后续逻辑读取的是同一个属性。
  2. 调整匹配逻辑遍历规则:逐个遍历当前分块的附件content,和原始DTO数组中每个元素的pdfBuffer做比对,不要拿单值和数组比较。
  3. Buffer内容比对使用Node.js内置的Buffer.equals()方法,该方法逐字节比对Buffer二进制内容,不依赖内存引用地址,只要内容一致就返回true。
  4. 修正附件拆分逻辑,按附件大小累加拆分,确保每个子块总大小不超过阈值,不要按元素个数平均拆分。

修复后核心代码片段

替换原else分支中匹配逻辑相关代码:

// 删除原错误匹配逻辑,替换为以下内容
console.log('original DTO list', this.getAmount);

// 遍历当前分块的每个附件
for (const att of attachment) {
  // 遍历原始DTO列表做匹配
  for (const element of this.getAmount) {
    // 先校验两者都是合法Buffer,再做内容比对
    if (
      Buffer.isBuffer(att.content) 
      && Buffer.isBuffer(element.pdfBuffer) 
      && att.content.equals(element.pdfBuffer)
    ) {
      console.log('match success, execute preset action');
      // 此处写入需要执行的预设业务逻辑
    }
  }
}

const link = ` (${index + 1}/${attachmentsChunk.length - 1})`;
const newContext = {
  getCurrent: link,
  ...context
}

return this.prepareEmail({
  para: to,
  asunto: ` ${subject} (Correo ${index + 1}/${attachmentsChunk.length - 1})`,
  plantilla: template,
  contexto: newContext,
}, attachment);

附件拆分逻辑修正参考

原按元素个数拆分的逻辑替换为按大小累加拆分,确保单块不超阈值:

// 替换原chunkSplit、attachmentsChunk计算逻辑
const attachmentsChunk: EmailAttachment[][] = [];
let currentChunk: EmailAttachment[] = [];
let currentChunkSize = 0;

for (const att of attachments) {
  const attSize = Buffer.isBuffer(att.content) ? att.content.length : 0;
  // 单个附件超过阈值的情况走原有上传Drive逻辑即可
  if (currentChunkSize + attSize > this.LIMIT_ATTACHMENTS && currentChunk.length > 0) {
    attachmentsChunk.push(currentChunk);
    currentChunk = [];
    currentChunkSize = 0;
  }
  currentChunk.push(att);
  currentChunkSize += attSize;
}
// 把最后一个块加入列表
if (currentChunk.length > 0) {
  attachmentsChunk.push(currentChunk);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:39:20