如何将 zip 文件编码为 multipart/form-data 的一部分

How to encode zip files as part of multipart/form-data

tldr 我在发送 zip 文件作为 multipart/form-data 请求正文的一部分时遇到编码问题。请帮助:/

我正在开发一个应该能够将 zip 文件上传到 Slack(通过他们的文件 api)的机器人,但我 运行 遇到了一些我认为相关的问题编码。

所以,我正在创建我的请求正文如下:

var form_string = "\n--abcdefghijklmnop\nContent-Disposition: form-data; filename=\"" + filename + "\"; name=\"file\";\nContent-Type:application/octet-stream;\nContent-Transfer-Encoding:base64;\n\n" + data;
form_string += "\n--abcdefghijklmnop\nContent-Disposition: form-data; name=\"token\";\n\n" + token;
form_string += "\n--abcdefghijklmnop\nContent-Disposition: form-data; name=\"filetype\";\n\n" + filetype;
form_string += "\n--abcdefghijklmnop\nContent-Disposition: form-data; name=\"filename\";\n\n" + filename;
form_string += "\n--abcdefghijklmnop\nContent-Disposition: form-data; name=\"channels\";\n\n" + channel;
form_string += "\n--abcdefghijklmnop\nContent-Disposition: form-data; name=\"title\";\n\n" + title;
form_string += "\n--abcdefghijklmnop--";

var form = Buffer.from(form_string, "utf8");

var headers = {
  "Content-Type": "multipart/form-data; boundary=abcdefghijklmnop",
  "Content-Length": form.length,
  "Authorization": "Bearer ....."
};
var options = {
  "headers": headers,
  "body": form 
};
// using the sync-request node module. 
var res = request("POST", url, options);

var res = request("POST", url, options);

(我也尝试过 application/zipapplication/x-zip-compressed。我也尝试过二进制和 base64 内容传输编码。)

(如果您想知道,我需要发出同步 http 请求...)

我创建了一个非常小的 zip 文件作为测试。它的base64编码如下:

UEsDBAoAAAAAAAqR+UoAAAAAAAAAAAAAAAAIABwAdGlueXppcC9VVAkAA1PBd1mDwXdZdXgLAAEE9QEAAAQUAAAAUEsDBAoAAAAAAAuR+Up6em/tAwAAAAMAAAAQABwAdGlueXppcC90aW55LnR4dFVUCQADVsF3WVzBd1l1eAsAAQT1AQAABBQAAABoaQpQSwECHgMKAAAAAAAKkflKAAAAAAAAAAAAAAAACAAYAAAAAAAAABAA7UEAAAAAdGlueXppcC9VVAUAA1PBd1l1eAsAAQT1AQAABBQAAABQSwECHgMKAAAAAAALkflKenpv7QMAAAADAAAAEAAYAAAAAAABAAAApIFCAAAAdGlueXppcC90aW55LnR4dFVUBQADVsF3WXV4CwABBPUBAAAEFAAAAFBLBQYAAAAAAgACAKQAAACPAAAAAAA=

我从 Slack 得到的东西似乎与原来的相似......也许......

UEsDBAoAAAAAAArCkcO5SgAAAAAAAAAAAAAAAAgAHAB0aW55emlwL1VUCQADU8OBd1nCg8OBd1l1eAsAAQTDtQEAAAQUAAAAUEsDBAoAAAAAAAvCkcO5Snp6b8OtAwAAAAMAAAAQABwAdGlueXppcC90aW55LnR4dFVUCQADVsOBd1lcw4F3WXV4CwABBMO1AQAABBQAAABoaQpQSwECHgMKAAAAAAAKwpHDuUoAAAAAAAAAAAAAAAAIABgAAAAAAAAAEADDrUEAAAAAdGlueXppcC9VVAUAA1PDgXdZdXgLAAEEw7UBAAAEFAAAAFBLAQIeAwoAAAAAAAvCkcO5Snp6b8OtAwAAAAMAAAAQABgAAAAAAAEAAADCpMKBQgAAAHRpbnl6aXAvdGlueS50eHRVVAUAA1bDgXdZdXgLAAEEw7UBAAAEFAAAAFBLBQYAAAAAAgACAMKkAAAAwo8AAAAAAA==

有人可以解释一下这里发生了什么编码以及我如何正确地将文件上传到 Slack 吗?谢谢!

下面的示例脚本怎么样?这种情况有 2 种模式。

示例脚本 1:

为此,我修改了您正在尝试的方法。您可以通过转换为字节数组来上传 zip 文件,如下所示。首先,它构建 form-data。它添加转换为字节数组的 zip 文件并使用 Buffer.concat() boundary。这用作请求中的正文。

var fs = require('fs');
var request = require('request');
var upfile = 'sample.zip';
fs.readFile(upfile, function(err, content){
    if(err){
        console.error(err);
    }
    var token = '### access token ###';
    var filetype = 'zip';
    var filename = 'samplefilename';
    var channel = 'sample';
    var title = 'sampletitle';
    var formString = "\n--abcdefghijklmnop\nContent-Disposition: form-data; name=\"token\";\n\n" + token;
    formString += "\n--abcdefghijklmnop\nContent-Disposition: form-data; name=\"filetype\";\n\n" + filetype;
    formString += "\n--abcdefghijklmnop\nContent-Disposition: form-data; name=\"filename\";\n\n" + filename;
    formString += "\n--abcdefghijklmnop\nContent-Disposition: form-data; name=\"channels\";\n\n" + channel;
    formString += "\n--abcdefghijklmnop\nContent-Disposition: form-data; name=\"title\";\n\n" + title;
    formString += "\n--abcdefghijklmnop\nContent-Disposition: form-data; filename=\"" + upfile + "\"; name=\"file\";\nContent-Type:application/octet-stream;\n\n";
    var options = {
        method: 'post',
        url: 'https://slack.com/api/files.upload',
        headers: {"Content-Type": "multipart/form-data; boundary=abcdefghijklmnop"},
        body: Buffer.concat([
            Buffer.from(formString, "utf8"),
            new Buffer(content, 'binary'),
            Buffer.from("\n--abcdefghijklmnop\n", "utf8"),
        ]),
    };
    request(options, function(error, response, body) {
        console.log(body);
    });
});

示例脚本 2:

这种方法比示例 1 更简单。您可以使用 fs.createReadStream() 作为文件上传到 Slack。

var fs = require('fs');
var request = require('request');
request.post({
    url: 'https://slack.com/api/files.upload',
    formData: {
        file: fs.createReadStream('sample.zip'),
        token: '### access token ###',
        filetype: 'zip',
        filename: 'samplefilename',
        channels: 'sample',
        title: 'sampletitle',
    },
}, function(error, response, body) {
    console.log(body);
});

结果:

示例 1 和示例 2 都可以按如下方式将 zip 文件上传到 Slack。对于两者,即使未定义 filetype,上传的文件也会自动用作 zip 文件。

如果我误解了你的问题,我很抱歉。