strong-tie/inbound-calls
0
1### A `FormData` polyfill for the browser ...and a module for NodeJS (`New!`)2 3```bash4npm install formdata-polyfill5```6 7The browser polyfill will likely have done its part already, and i hope you stop supporting old browsers c",)<br>8But NodeJS still laks a proper FormData<br>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.9 10### The NodeJS / ESM version11- The modular (~2.3 KiB minified uncompressed) version of this package is independent of any browser stuff and don't patch anything12- It's as pure/spec compatible as it possible gets the test are run by WPT.13- It's compatible with [node-fetch](https://github.com/node-fetch/node-fetch).14- It have higher platform dependencies as it uses classes, symbols, ESM & private fields15- Only dependency it has is [fetch-blob](https://github.com/node-fetch/fetch-blob)16 17```js18// Node example19import fetch from 'node-fetch'20import File from 'fetch-blob/file.js'21import { fileFromSync } from 'fetch-blob/from.js'22import { FormData } from 'formdata-polyfill/esm.min.js'23 24const file = fileFromSync('./README.md')25const fd = new FormData()26 27fd.append('file-upload', new File(['abc'], 'hello-world.txt'))28fd.append('file-upload', file)29 30// it's also possible to append file/blob look-a-like items31// if you have streams coming from other destinations32fd.append('file-upload', {33 size: 123,34 type: '',35 name: 'cat-video.mp4',36 stream() { return stream },37 [Symbol.toStringTag]: 'File'38})39 40fetch('https://httpbin.org/post', { method: 'POST', body: fd })41```42 43----44 45It also comes with way to convert FormData into Blobs - it's not something that every developer should have to deal with.46It's mainly for [node-fetch](https://github.com/node-fetch/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](https://github.com/jimmywarting/FormData/blob/5ddea9e0de2fc5e246ab1b2f9d404dee0c319c02/formdata-to-blob.js) to the core and passes all WPT tests run by the browser itself)47```js48import { Readable } from 'node:stream'49import { FormData, formDataToBlob } from 'formdata-polyfill/esm.min.js'50 51const blob = formDataToBlob(new FormData())52fetch('https://httpbin.org/post', { method: 'POST', body: blob })53 54// node built in http and other similar http library have to do:55const stream = Readable.from(blob.stream())56const req = http.request('http://httpbin.org/post', {57 method: 'post',58 headers: {59 'Content-Length': blob.size,60 'Content-Type': blob.type61 }62})63stream.pipe(req)64```65 66PS: blob & file that are appended to the FormData will not be read until any of the serialized blob read-methods gets called67...so uploading very large files is no biggie68 69### Browser polyfill70 71usage:72 73```js74import 'formdata-polyfill' // that's it75```76 77The browser polyfill conditionally replaces the native implementation rather than fixing the missing functions,78since otherwise there is no way to get or delete existing values in the FormData object.79Therefore this also patches `XMLHttpRequest.prototype.send` and `fetch` to send the `FormData` as a blob,80and `navigator.sendBeacon` to send native `FormData`.81 82I was unable to patch the Response/Request constructor83so if you are constructing them with FormData then you need to call `fd._blob()` manually.84 85```js86new Request(url, {87 method: 'post',88 body: fd._blob ? fd._blob() : fd89})90```91 92Dependencies93---94 95If you need to support IE <= 9 then I recommend you to include eligrey's [blob.js]96(which i hope you don't - since IE is now dead)97 98<details>99 <summary>Updating from 2.x to 3.x</summary>100 101Previously you had to import the polyfill and use that,102since it didn't replace the global (existing) FormData implementation.103But now it transparently calls `_blob()` for you when you are sending something with fetch or XHR,104by way of monkey-patching the `XMLHttpRequest.prototype.send` and `fetch` functions.105 106So you maybe had something like this:107 108```javascript109var FormData = require('formdata-polyfill')110var fd = new FormData(form)111xhr.send(fd._blob())112```113 114There is no longer anything exported from the module115(though you of course still need to import it to install the polyfill),116so you can now use the FormData object as normal:117 118```javascript119require('formdata-polyfill')120var fd = new FormData(form)121xhr.send(fd)122```123 124</details>125 126 127 128Native Browser compatibility (as of 2021-05-08)129---130Based on this you can decide for yourself if you need this polyfill.131 132[](https://developer.mozilla.org/en-US/docs/Web/API/FormData#Browser_compatibility)133 134 135 136This normalizes support for the FormData API:137 138 - `append` with filename139 - `delete()`, `get()`, `getAll()`, `has()`, `set()`140 - `entries()`, `keys()`, `values()`, and support for `for...of`141 - Available in web workers (just include the polyfill)142 143 [npm-image]: https://img.shields.io/npm/v/formdata-polyfill.svg144 [npm-url]: https://www.npmjs.com/package/formdata-polyfill145 [blob.js]: https://github.com/eligrey/Blob.js146 