4

There are lots of posts about how to handle request with multipart form data . But my use case is that I have a client that expects multipart form data response from server, and I need to write a simple nodejs server in order to test my client.

To write the simple server, I have the following:

var express = require('express');
var bodyParser = require('body-parser');
var FormData = require('form-data');

var app = express();

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());


app.get('/describe', function(req, res) {
  var form = new FormData();
  form.append('part1', 'part 1 data');
  form.append('part2', 'part 2 data');
  res.setHeader('Content-Type', 'multipart/form-data');
  res.send(form);
});

app.listen(3030, "0.0.0.0");
console.log('Listening on port 3030...');

Now when my client request localhost:3030/describe, the response header shows the following without the boundary value

Content-Type: multipart/form-data; charset=utf-8 

And the content is downloaded as file instead of in the response body.

{"_overheadLength":208,"_valueLength":22,"_valuesToMeasure":[],"writable":false,"readable":true,"dataSize":0,"maxDataSize":2097152,"pauseStreams":true,"_released":false,"_streams":["----------------------------315683163006570790405079\r\nContent-Disposition: form-data; name=\"part1\"\r\n\r\n","part 1 data",null,"----------------------------315683163006570790405079\r\nContent-Disposition: form-data; name=\"part2\"\r\n\r\n","part 2 data",null],"_currentStream":null,"_boundary":"--------------------------315683163006570790405079"}

So my questions: 1. how do we make the boundary appears in the response header? 2. how do we make the form data response content show up in the response body instead as download file?

2
  • One fundamental issue here is that the HTTP protocol never intended multipart/form-data as part of a response cycle, but only as part of the request cycle. If you want the browser to understand the various fields in the body, you'll need to implement your own client-side parser for the response from the server, as this is a very unconventional API. Commented Jun 16, 2018 at 0:58
  • thank you Patrick! Yes I have to write my own client-side parser to understand the response from the server and would like to make sure my client side parsing logic can work with any real life form-data response, not just the one sent from my test server. :) Commented Jun 18, 2018 at 18:41

2 Answers 2

17

To send your form data you'll want to pipe it (see documentation), like this:

form.pipe(res);

To add the boundary into the header, you can do something like this:

res.setHeader('Content-Type', 'multipart/form-data; boundary='+form.getBoundary());

Now, about the "save as" box: The browser uses content-type to figure out what to do with the file. So if you want it to be displayed in the browser window, a good choice would be text/plain (or possibly text/html if that doesn't work). Then you could put your multipart/form-data into something like x-content-type.

(I'm assuming eventually you'll be using XHR or fetch, and at that point you can switch the content-type back. the text/plain thing is just a temporary solution to get the data to show up in a standard web browser for testing.)

Putting it all together:

app.get('/describe', function(req, res) {
  var form = new FormData();
  form.append('part1', 'part 1 data');
  form.append('part2', 'part 2 data');
  res.setHeader('x-Content-Type', 'multipart/form-data; boundary='+form._boundary);
  res.setHeader('Content-Type', 'text/plain');
  form.pipe(res);
});
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you David784! Your suggestion definitely worked. Thanks again!
@Jing you're welcome...if you get a chance, would you mind upvoting and accepting the answer?
the 'content-type', not 'Content-Type', because body.js is obtaining content type by: const ct = this.headers.get('content-type'); if (ct.startsWith('application/x-www-form-urlencoded')). It becomes null otherwise and error is thrown.
-2

In my case, it was POST request that was being called by a webhook and I used multer did the magic too. Here is the code.

const express = require('express');
const bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.post('/', upload.none(), function (req, res) {
  console.log("Data",req.body) 
  res.status(200).send('OK');
});

app.listen(port);

2 Comments

Your solution is about sending request with multipart/form-data, not response.
@cedenzah My solution works for me. Like I said I was trying to get data from a webhook. req.body sends has the data I need from the webhook.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.