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

如何用SuiteScript实现等效cURL的multipart/form-data二进制ZIP上传?

NetSuite SuiteScript实现multipart/form-data二进制文件上传问题

需求与问题背景

在NetSuite中开发Map/Reduce脚本,通过N/compress生成ZIP文件,需要以HTTPS POST的multipart/form-data格式上传至第三方API。API要求接收原始二进制ZIP文件,不支持Base64编码。已通过Postman/cURL验证API正常,cURL示例如下:

curl --location 'https://<endpoint>/documents/zip' \
--header 'Authorization: <JWT_TOKEN>' \
--form 'file=@"file.zip"' \
--form 'companyId=<COMPANY_ID>'

现有代码尝试手动构建multipart请求体,但无法正确发送原始二进制文件,核心疑问:

  • 如何实现等效于cURL --form 'file=@file.zip'的原始二进制文件上传?
  • NetSuite是否有官方支持/推荐的方案,用于向不接受Base64的第三方API上传二进制文件?

现有代码片段:

var zipContent = zipFile.getContents(); // ZIP from File Cabinet

var body = [];
body.push('--' + boundary);
body.push('Content-Disposition: form-data; name="companyId"');
body.push('');
body.push(companyId);

body.push('--' + boundary);
body.push('Content-Disposition: form-data; name="file"; filename="' + zipFile.name + '"');
body.push('Content-Type: application/zip');
body.push('');
body.push(zipContent);

body.push('--' + boundary + '--');

var response = https.post({
    url: uploadUrl,
    headers: {
        'Authorization': 'Bearer ' + token,
        'Content-Type': 'multipart/form-data; boundary=' + boundary
    },
    body: body.join('\r\n')
});

解决方案

你的核心问题是:zipFile.getContents()返回的是Base64编码字符串,直接用字符串拼接请求体会破坏原始二进制结构。以下是NetSuite官方推荐的处理方案:

方法:二进制缓冲区拼接请求体

利用N/encode模块将Base64编码的文件内容转为二进制缓冲区,再将表单文本部分、二进制文件、结尾边界合并为完整的二进制请求体,避免字符串编码导致的文件损坏。

完整示例代码:

define(['N/file', 'N/https', 'N/encode', 'N/log'], function(file, https, encode, log) {
    function execute() {
        // 配置参数
        const zipFileId = '替换为你的ZIP文件柜ID';
        const jwtToken = '替换为你的JWT Token';
        const targetCompanyId = '替换为你的Company ID';
        const uploadEndpoint = 'https://<endpoint>/documents/zip';
        const boundary = `----NS-Multipart-Boundary-${Date.now()}`;

        // 加载ZIP文件
        const zipFile = file.load({ id: zipFileId });

        // 构建表单字段的文本头部
        const formPart = [
            `--${boundary}`,
            'Content-Disposition: form-data; name="companyId"',
            '',
            targetCompanyId,
            `--${boundary}`,
            `Content-Disposition: form-data; name="file"; filename="${zipFile.name}"`,
            'Content-Type: application/zip',
            '', // 头部与二进制内容之间必须有空白行
            ''
        ].join('\r\n');

        // 构建请求结尾边界
        const endBoundary = `\r\n--${boundary}--`;

        // 将文本部分转为二进制缓冲区
        const formPartBuffer = encode.convert({
            string: formPart,
            inputEncoding: encode.Encoding.UTF_8,
            outputEncoding: encode.Encoding.BINARY
        });

        // 将ZIP文件的Base64内容转为原始二进制缓冲区
        const zipBinaryBuffer = encode.convert({
            string: zipFile.getContents(),
            inputEncoding: encode.Encoding.BASE_64,
            outputEncoding: encode.Encoding.BINARY
        });

        // 将结尾边界转为二进制缓冲区
        const endBoundaryBuffer = encode.convert({
            string: endBoundary,
            inputEncoding: encode.Encoding.UTF_8,
            outputEncoding: encode.Encoding.BINARY
        });

        // 合并所有二进制部分
        const fullRequestBody = formPartBuffer + zipBinaryBuffer + endBoundaryBuffer;

        // 发送POST请求
        const response = https.post({
            url: uploadEndpoint,
            headers: {
                'Authorization': `Bearer ${jwtToken}`,
                'Content-Type': `multipart/form-data; boundary=${boundary}`
            },
            body: fullRequestBody
        });

        log.debug('上传结果', response.body);
    }

    return { execute };
});

关键注意事项

  • 禁止字符串拼接二进制数据:字符串会自动将二进制转为UTF-8编码,破坏ZIP文件的原始字节结构
  • 边界唯一性:建议加入时间戳生成唯一边界,避免与文件内容冲突
  • 格式规范:每个表单部分的头部与内容之间必须用\r\n\r\n分隔(代码中通过空行实现)
  • 结尾边界格式:必须以--boundary--结尾,前面需添加换行符

官方支持说明

NetSuite官方文档明确指出,向第三方API上传二进制文件时,必须通过N/encode.convert将Base64编码的文件内容转换为二进制格式,再构建符合multipart/form-data规范的请求体。可参考N/encode模块的convert方法、N/https模块的POST请求参数说明。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 15:05:04