Replacements for form-data
FormData is built into Node.js and all modern browsers, and fetch sends it without any extra packages.
FormData (native, since Node.js 18.0.0)
The native FormData works with fetch, which sets the Content-Type header, including the boundary, for you. Don't set that header yourself.
import FormData from 'form-data'
const form = new FormData()
form.append('name', 'Jane')
await fetch('https://example.com/upload', {
method: 'POST',
headers: form.getHeaders(),
body: form
})Buffers
Wrap the data in a Blob, and pass the filename as the third argument. Set the content type on the Blob, since it isn't guessed from the filename.
form.append('image', buffer, { filename: 'photo.png', contentType: 'image/png' })
form.append('image', new Blob([buffer], { type: 'image/png' }), 'photo.png') Files
Use fs.openAsBlob (since Node.js 19.8.0) instead of a read stream. Unlike form-data, the filename and content type aren't taken from the path, so pass them yourself.
import fs from 'node:fs'
import { openAsBlob } from 'node:fs'
form.append('report', fs.createReadStream('./report.pdf'))
form.append('report', await openAsBlob('./report.pdf', { type: 'application/pdf' }), 'report.pdf') For other streams, read them into a Blob first, for example with node:stream/consumers:
import { buffer } from 'node:stream/consumers'
form.append('data', new Blob([await buffer(stream)]), 'data.bin')submit()
Use fetch instead.
form.submit('https://example.com/upload', (err, res) => {
// ...
})
const res = await fetch('https://example.com/upload', { method: 'POST', body: form }) getHeaders(), getBuffer() and getLength()
If you need the encoded body without fetch, for example to send it with node:http, encode the form with a Response. Its Content-Type header includes the generated boundary.
const headers = form.getHeaders()
const body = form.getBuffer()
const encoded = new Response(form)
const headers = { 'content-type': encoded.headers.get('content-type') }
const body = Buffer.from(await encoded.arrayBuffer())
http.request(url, { method: 'POST', headers: { ...headers, 'content-length': body.length } }).end(body)The native FormData always generates its own boundary, so there is no equivalent to setBoundary().