Note: FormData is built in to NodeJS v18 globally so that you no longer need this.
FormData
polyfill for the browser ...and a module for NodeJS (New!
)npm install formdata-polyfill
The browser polyfill will likely have done its part already, and i hope you stop supporting old browsers c",)
But NodeJS still lacks a proper FormData
The good old form-data package is a very old and isn't spec compatible and does some abnormal stuff to construct and read FormData instances that other http libraries are not happy about when it comes to follow the spec.
// Node example
import fetch from 'node-fetch'
import File from 'fetch-blob/file.js'
import { fileFromSync } from 'fetch-blob/from.js'
import { FormData } from 'formdata-polyfill/esm.min.js'
const file = fileFromSync('./README.md')
const fd = new FormData()
fd.append('file-upload', new File(['abc'], 'hello-world.txt'))
fd.append('file-upload', file)
// it's also possible to append file/blob look-a-like items
// if you have streams coming from other destinations
fd.append('file-upload', {
size: 123,
type: '',
name: 'cat-video.mp4',
stream() { return stream },
[Symbol.toStringTag]: 'File'
})
fetch('https://httpbin.org/post', { method: 'POST', body: fd })
It also comes with way to convert FormData into Blobs - it's not something that every developer should have to deal with. It's mainly for node-fetch and other http library to ease the process of serializing a FormData into a blob and just wish to deal with Blobs instead (Both Deno and Undici adapted a version of this formDataToBlob to the core and passes all WPT tests run by the browser itself)
import { Readable } from 'node:stream'
import { FormData, formDataToBlob } from 'formdata-polyfill/esm.min.js'
const blob = formDataToBlob(new FormData())
fetch('https://httpbin.org/post', { method: 'POST', body: blob })
// node built in http and other similar http library have to do:
const stream = Readable.from(blob.stream())
const req = http.request('http://httpbin.org/post', {
method: 'post',
headers: {
'Content-Length': blob.size,
'Content-Type': blob.type
}
})
stream.pipe(req)
PS: blob & file that are appended to the FormData will not be read until any of the serialized blob read-methods gets called ...so uploading very large files is no biggie
usage:
import 'formdata-polyfill' // that's it
The browser polyfill conditionally replaces the native implementation rather than fixing the missing functions,
since otherwise there is no way to get or delete existing values in the FormData object.
Therefore this also patches XMLHttpRequest.prototype.send
and fetch
to send the FormData
as a blob,
and navigator.sendBeacon
to send native FormData
.
I was unable to patch the Response/Request constructor
so if you are constructing them with FormData then you need to call fd._blob()
manually.
new Request(url, {
method: 'post',
body: fd._blob ? fd._blob() : fd
})
If you need to support IE <= 9 then I recommend you to include eligrey's blob.js (which i hope you don't - since IE is now dead)
Based on this you can decide for yourself if you need this polyfill.
This normalizes support for the FormData API:
append
with filenamedelete()
, get()
, getAll()
, has()
, set()
entries()
, keys()
, values()
, and support for for...of