简体   繁体   中英

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

tldr I'm having encoding issues when sending zip files as part of a multipart/form-data request body. Help please :/

I'm working on a bot that should be able to upload zip files to Slack (via their file api), but I'm running into some issues that I believe are related to encoding.

So, I'm creating my request body as follows:

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);

(I've tried application/zip and application/x-zip-compressed as well. I've also tried both binary and base64 content transfer encodings.)

(And in case you're wondering, I need to make synchronous http requests...)

I created a really small zip file as a test. The base64 encoding of it is below:

UEsDBAoAAAAAAAqR+UoAAAAAAAAAAAAAAAAIABwAdGlueXppcC9VVAkAA1PBd1mDwXdZdXgLAAEE9QEAAAQUAAAAUEsDBAoAAAAAAAuR+Up6em/tAwAAAAMAAAAQABwAdGlueXppcC90aW55LnR4dFVUCQADVsF3WVzBd1l1eAsAAQT1AQAABBQAAABoaQpQSwECHgMKAAAAAAAKkflKAAAAAAAAAAAAAAAACAAYAAAAAAAAABAA7UEAAAAAdGlueXppcC9VVAUAA1PBd1l1eAsAAQT1AQAABBQAAABQSwECHgMKAAAAAAALkflKenpv7QMAAAADAAAAEAAYAAAAAAABAAAApIFCAAAAdGlueXppcC90aW55LnR4dFVUBQADVsF3WXV4CwABBPUBAAAEFAAAAFBLBQYAAAAAAgACAKQAAACPAAAAAAA=

What I'm getting from Slack seems to be similar to the original... maybe...

UEsDBAoAAAAAAArCkcO5SgAAAAAAAAAAAAAAAAgAHAB0aW55emlwL1VUCQADU8OBd1nCg8OBd1l1eAsAAQTDtQEAAAQUAAAAUEsDBAoAAAAAAAvCkcO5Snp6b8OtAwAAAAMAAAAQABwAdGlueXppcC90aW55LnR4dFVUCQADVsOBd1lcw4F3WXV4CwABBMO1AQAABBQAAABoaQpQSwECHgMKAAAAAAAKwpHDuUoAAAAAAAAAAAAAAAAIABgAAAAAAAAAEADDrUEAAAAAdGlueXppcC9VVAUAA1PDgXdZdXgLAAEEw7UBAAAEFAAAAFBLAQIeAwoAAAAAAAvCkcO5Snp6b8OtAwAAAAMAAAAQABgAAAAAAAEAAADCpMKBQgAAAHRpbnl6aXAvdGlueS50eHRVVAUAA1bDgXdZdXgLAAEEw7UBAAAEFAAAAFBLBQYAAAAAAgACAMKkAAAAwo8AAAAAAA==

Could someone explain what encoding is going on here and how I can correctly upload a file to Slack? Thanks!

How about following sample scripts? There are 2 patterns for this situation.

Sample script 1 :

For this, I modified the method you are trying. You can upload the zip file by converting to the byte array as follows. At first, it builds form-data . It adds the zip file converted to byte array and boundary using Buffer.concat() . This is used as body in request.

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);
    });
});

Sample script 2 :

This is a simpler way than sample 1. You can use fs.createReadStream() as a file for uploading to 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);
});

Result :

Both sample 1 and sample 2 can be uploaded zip file to Slack as follows. For both, even if filetype is not defined, the uploaded file is used automatically as a zip file.

在此处输入图片说明

If I misunderstand your question, I'm sorry.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM