J Johnson
J Johnson

Reputation: 145

How do I upload a file using multipart/form-data header with native Node.js https.request?

I am trying to upload a file from my computer using native https.request from node.js. My code look like this:

let query = require('https').request({
  hostname: 'somehost.com',
  path: '/path/to/upload',
  headers: {'Content-Type': 'multipart/form-data'},
  method: 'POST'
}, (res) => {
  let data = '';
  res.on("data", (chunk) => {
    data += chunk.toString('utf8');
  });
  res.on('end', () => {
    console.log("data");
  })
});
query.on("error", (e) => {
  console.error(e);
});
query.write(Buffer[
  {key1: 1, file: require("fs").createReadStream("/path/to/file.txt")}
]);      // I don't know how to put here
query.end();

I don't get any response from host, the file failed to upload. How can I do this?

Upvotes: 2

Views: 4105

Answers (1)

Kirk Larkin
Kirk Larkin

Reputation: 93023

When uploading multipart/form-data, the Content-Type header must include a boundary, in order to indicate where each "part" lives within the posted data. In order to set the boundary for The Multipart Content-Type, you can use the form-data package from NPM. You could set the header/boundary manually, but the form-data package will handle this for you and free you from having to worry about the details, etc.

In order to use form-data in your example, you will need to do the following:

  1. Create a new FormData object and append the relevant parts:

    let formData = new require('form-data')();
    formData.append('key1', 1);
    formData.append('file', require("fs").createReadStream("/path/to/file.txt"));
    
  2. Use the getHeaders function to build the correct HTTP headers:

    require('https').request({
        headers: formData.getHeaders(),
        // ...
    }
    
  3. Use pipe in order to allow form-data to process your data and send it to the server:

    formData.pipe(query);
    

    With this change, you no longer need your calls to query.write or query.end - the call to pipe takes care of that.

For completeness, here's the final code with the changes I described:

let formData = new require('form-data')();
formData.append('key1', 1);
formData.append('file', require("fs").createReadStream("/path/to/file.txt"));

let query = require('https').request({
    hostname: 'somehost.com',
    path: '/path/to/upload',
    method: 'POST',
    headers: formData.getHeaders()
}, (res) => {
    let data = '';
    res.on("data", (chunk) => {
        data += chunk.toString('utf8');
    });
    res.on('end', () => {
        console.log(data);
    })
});

query.on("error", (e) => {
    console.error(e);
});

formData.pipe(query);

Upvotes: 2

Related Questions