What is formdata-polyfill?
The formdata-polyfill npm package provides a polyfill for the FormData Web API, which allows developers to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest or fetch API. It is particularly useful for ensuring compatibility with older browsers that do not support the FormData API natively.
What are formdata-polyfill's main functionalities?
FormData Polyfill
This code checks if the FormData API is not available in the current browser environment and if so, it requires the formdata-polyfill package. After requiring the polyfill, you can use the FormData constructor to create a new FormData object and use the append method to add key/value pairs to it.
if (!window.FormData) {
require('formdata-polyfill');
}
// Now you can use FormData as if the browser supports it natively.
var formData = new FormData();
formData.append('key', 'value');
formData.append('file', fileInput.files[0]);
Sending FormData with fetch
This code demonstrates how to use the formdata-polyfill to send form data using the fetch API. It creates a new FormData object, appends some data to it, and then sends it to a server endpoint using the POST method.
require('formdata-polyfill');
var formData = new FormData();
formData.append('username', 'example');
formData.append('avatar', fileInput.files[0]);
fetch('/submit-form', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(result => console.log(result))
.catch(error => console.error('Error:', error));
Other packages similar to formdata-polyfill
form-data
The 'form-data' npm package is similar to formdata-polyfill in that it allows you to create and submit FormData objects. However, it is designed to be used in a Node.js environment rather than in the browser. It can be particularly useful when you need to simulate form submission from a server-side application.
isomorphic-form-data
The 'isomorphic-form-data' package provides a FormData implementation that works both in the browser and in Node.js environments. This can be useful for code that needs to run in both contexts without changes. It is similar to formdata-polyfill but with the added benefit of being isomorphic.
A 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 laks a proper FormData
The good old form-data package is a very old and isn't spec compatible and dose some abnormal stuff to construct and read FormData instances that other http libraries are not happy about when it comes to follow the spec.
The NodeJS / ESM version
- The modular (~1500 B minified uncompressed) version of this package is independent of any browser stuff and don't patch anything
- It's as pure/spec compatible as it possible gets.
- It's compatible with node-fetch.
- It have higher platform dependencies as it uses classes, symbols & private fields
- Only dependency it has is fetch-blob
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)
fd.append('file-upload', {
size: 123,
type: '',
name: 'cat.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
See code example
import { formDataToBlob } from 'formdata-polyfill/esm.min.js'
const blob = formDataToBlob(formData)
fetch('https://httpbin.org/post', { method: 'POST', body: blob })
const stream = 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
Browser polyfill
usage:
import 'formdata-polyfill'
The browser polyfill conditionally replaces the native implementation rather then 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
})
Dependencies
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)
Updating from 2.x to 3.x
Previously you had to import the polyfill and use that,
since it didn't replace the global (existing) FormData implementation.
But now it transparently calls _blob()
for you when you are sending something with fetch or XHR,
by way of monkey-patching the XMLHttpRequest.prototype.send
and fetch
functions.
So you maybe had something like this:
var FormData = require('formdata-polyfill')
var fd = new FormData(form)
xhr.send(fd._blob())
There is no longer anything exported from the module
(though you of course still need to import it to install the polyfill),
so you can now use the FormData object as normal:
require('formdata-polyfill')
var fd = new FormData(form)
xhr.send(fd)
Native Browser compatibility (as of 2021-05-08)
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
- Available in web workers (just include the polyfill)