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

如何仅用vanilla Node.js构造含二进制文件的multipart/form-data报文

Code by Zapier 无依赖构造multipart/form-data报文方案

有完全基于 vanilla Node.js 即可实现的方案,无需依赖任何第三方npm包,核心逻辑是手动拼接符合HTTP协议规范的multipart/form-data报文。

实现原理

multipart/form-data报文结构遵循固定的HTTP协议规则,只要按规则拼接即可:

  • 首先生成一个唯一的边界字符串(boundary),作用是分隔不同的表单字段,需保证不会出现在任何字段的内容中
  • 每个表单字段的结构固定:-- + 边界字符串 + CRLF换行 + 字段头描述 + 两次CRLF换行 + 字段值 + CRLF换行
  • 所有字段拼接完成后,末尾需要拼接-- + 边界字符串 + -- + CRLF作为报文结束标识
  • 二进制文件类型的字段,需要额外在头信息中指定filename属性和对应Content-Type,内容直接传入二进制Buffer即可

可直接在Code by Zapier中运行的示例代码

const http = require('http');
const fs = require('fs'); // 仅读取本地文件时使用,Zapier中可直接用步骤传入的Buffer

// 1. 生成唯一边界字符串
const BOUNDARY = `----ZapierFormBoundary${Date.now()}${Math.random().toString(16).slice(2)}`;
const CRLF = '\r\n';

// 2. 准备要提交的字段:示例包含普通文本字段和二进制文件字段
const formFields = [
  // 普通文本字段
  {
    name: 'username',
    value: 'test_user'
  },
  // 二进制文件字段
  {
    name: 'avatar',
    filename: 'avatar.png',
    contentType: 'image/png',
    // 这里替换为你实际拿到的文件Buffer,比如Zapier触发步骤传入的文件二进制
    value: fs.readFileSync('./test_avatar.png')
  }
];

// 3. 拼接表单报文
const chunks = [];
for (const field of formFields) {
  // 拼接字段开头边界和头信息
  chunks.push(Buffer.from(`--${BOUNDARY}${CRLF}`));
  if (field.filename) {
    // 文件字段头
    chunks.push(Buffer.from(`Content-Disposition: form-data; name="${field.name}"; filename="${field.filename}"${CRLF}`));
    chunks.push(Buffer.from(`Content-Type: ${field.contentType}${CRLF}`));
  } else {
    // 普通文本字段头
    chunks.push(Buffer.from(`Content-Disposition: form-data; name="${field.name}"${CRLF}`));
    chunks.push(Buffer.from(`Content-Type: text/plain; charset=utf-8${CRLF}`));
  }
  // 头和值之间的空行
  chunks.push(Buffer.from(CRLF));
  // 字段值
  chunks.push(Buffer.isBuffer(field.value) ? field.value : Buffer.from(field.value));
  // 字段结尾换行
  chunks.push(Buffer.from(CRLF));
}
// 拼接整个表单的结束边界
chunks.push(Buffer.from(`--${BOUNDARY}--${CRLF}`));
const fullBody = Buffer.concat(chunks);

// 4. 发送请求示例
const options = {
  hostname: '你的目标接口域名',
  port: 80,
  path: '你的接口路径',
  method: 'POST',
  headers: {
    'Content-Type': `multipart/form-data; boundary=${BOUNDARY}`,
    'Content-Length': fullBody.length
  }
};

const req = http.request(options, (res) => {
  let resData = '';
  res.on('data', (chunk) => {
    resData += chunk;
  });
  res.on('end', () => {
    console.log('请求成功', resData);
    // Zapier中可以直接output结果给后续步骤使用
    output = { success: true, response: resData };
  });
});

req.on('error', (e) => {
  console.error('请求出错', e);
  output = { success: false, error: e.message };
});

req.write(fullBody);
req.end();

注意事项

  • 边界字符串建议用时间戳加随机字符串拼接生成,避免和表单内容重复导致解析失败
  • 所有换行必须使用\r\n(CRLF),不能用\n,否则大部分服务端会无法正常解析表单
  • 二进制内容直接传入Buffer即可,不要调用toString()方法做编码转换,否则会导致文件损坏
  • 如果使用Zapier内置的fetch方法发送请求,直接将拼接好的fullBody作为body参数传入,对应配置headers即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 12:45:02