• Stars
    star
    359
  • Rank 118,537 (Top 3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created about 8 years ago
  • Updated 10 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

HTML5 `FormData` polyfill for Browsers and nodejs

Note: FormData is built in to NodeJS v18 globally so that you no longer need this.

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 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.

The NodeJS / ESM version

  • The modular (~2.3 KiB 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 the test are run by WPT.
  • It's compatible with node-fetch.
  • It have higher platform dependencies as it uses classes, symbols, ESM & private fields
  • Only dependency it has is fetch-blob
// 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

Browser polyfill

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
})

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.

screenshot

This normalizes support for the FormData API:

  • append with filename
  • delete(), get(), getAll(), has(), set()
  • entries(), keys(), values(), and support for for...of
  • Available in web workers (just include the polyfill)

More Repositories

1

StreamSaver.js

StreamSaver writes stream to the filesystem directly asynchronous
JavaScript
3,873
star
2

native-file-system-adapter

File system, based on the spec reference implementation
JavaScript
446
star
3

ofc

Online font converter
CSS
133
star
4

wemo-client

JavaScript client library for controlling and subscribing to Wemo Devices
JavaScript
132
star
5

webtorrent-server-browser

test torrent.createServer using service worker
JavaScript
21
star
6

Screw-FileReader

For those who don't like the FileReader
JavaScript
21
star
7

you-might-not-need-typescript

Goes to show how much i don't want to use typescript
HTML
20
star
8

ga-api

Google Analytics API access
JavaScript
16
star
9

fetch-headers

fetch headers polyfill
JavaScript
14
star
10

not-a-log

A tiny console interface that returns everything as a string
JavaScript
12
star
11

node-domexception

An implementation of the DOMException class from NodeJS
JavaScript
9
star
12

cache-polyfill

cache polyfill, Offline storage, Wraps IndexedDB, without https/ssl
JavaScript
9
star
13

browser-su

JavaScript
8
star
14

lazy-resolver

Skip hoops with promises, make async code sync-ish looking (it is still async)
JavaScript
7
star
15

fetch-event

FetchEvent outside Service Worker
JavaScript
3
star
16

zip-go

Small, zero dependent, cross friendly zip tool
JavaScript
3
star
17

stream-consumers

a user-land copy of the node:stream/consumers library from Node.js
JavaScript
3
star
18

to-uint8array

Convert anything to Uint8Array without a copy
JavaScript
3
star
19

await-sync

Perform async work synchronously using web worker and SharedArrayBuffer
JavaScript
3
star
20

fetch-cachestorage

html5 CacheStorage for node
JavaScript
2
star
21

3th-party-structured-clone-wpt

JavaScript
2
star
22

update-notifier-go

Minimal dependency free update notifier
JavaScript
1
star
23

missing-dom-events

The missing DOM events for backends that doesn't support them
JavaScript
1
star
24

highlight-saas

Highlight.js as a service
HTML
1
star
25

abortcontroller

AbortController for node
JavaScript
1
star
26

mediquerie

Angular directive that allows you to use css media query on any element
JavaScript
1
star
27

diezyweb

Take a different look at your hard drive with your browser
JavaScript
1
star
28

itty-compressor

A tiny compression library that leverages (De)CompressionStream and Response
JavaScript
1
star
29

sw-renderer

Offline first streaming ES6 template engine
HTML
1
star
30

groupby-polyfill

small zero dependent polyfill for `Object.groupBy` and `Map.groupBy`
JavaScript
1
star