# FormData
Spec-compliant [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) implementation for Node.js
[![Code Coverage](https://codecov.io/github/octet-stream/form-data/coverage.svg?branch=master)](https://codecov.io/github/octet-stream/form-data?branch=master)
[![CI](https://github.com/octet-stream/form-data/workflows/CI/badge.svg)](https://github.com/octet-stream/form-data/actions/workflows/ci.yml)
[![ESLint](https://github.com/octet-stream/form-data/workflows/ESLint/badge.svg)](https://github.com/octet-stream/form-data/actions/workflows/eslint.yml)
## Highlights
1. Spec-compliant: implements every method of the [`FormData interface`](https://developer.mozilla.org/en-US/docs/Web/API/FormData).
2. Supports Blobs and Files sourced from anywhere: you can use builtin [`fileFromPath`](#filefrompathpath-filename-options---promisefile) and [`fileFromPathSync`](#filefrompathsyncpath-filename-options---file) helpers to create a File from FS, or you can implement your `BlobDataItem` object to use a different source of data.
3. Supports both ESM and CJS targets. See [`ESM/CJS support`](#esmcjs-support) section for details.
4. Written on TypeScript and ships with TS typings.
5. Isomorphic, but only re-exports native FormData object for browsers. If you need a polyfill for browsers, use [`formdata-polyfill`](https://github.com/jimmywarting/FormData)
6. It's a [`ponyfill`](https://ponyfill.com/)! Which means, no effect has been caused on `globalThis` or native `FormData` implementation.
## Installation
You can install this package with npm:
```
npm install formdata-node
```
Or yarn:
```
yarn add formdata-node
```
Or pnpm
```
pnpm add formdata-node
```
## ESM/CJS support
This package is targeting ESM and CJS for backwards compatibility reasons and smoothen transition period while you convert your projects to ESM only. Note that CJS support will be removed as [Node.js v12 will reach its EOL](https://github.com/nodejs/release#release-schedule). This change will be released as major version update, so you won't miss it.
## Usage
1. Let's take a look at minimal example with [got](https://github.com/sindresorhus/got):
```js
import {FormData} from "formdata-node"
// I assume Got >= 12.x is used for this example
import got from "got"
const form = new FormData()
form.set("greeting", "Hello, World!")
const data = await got.post("https://httpbin.org/post", {body: form}).json()
console.log(data.form.greeting) // => Hello, World!
```
2. If your HTTP client does not support spec-compliant FormData, you can use [`form-data-encoder`](https://github.com/octet-stream/form-data-encoder) to encode entries:
```js
import {Readable} from "stream"
import {FormDataEncoder} from "form-data-encoder"
import {FormData} from "formdata-node"
// Note that `node-fetch` >= 3.x have builtin support for spec-compliant FormData, sou you'll only need the `form-data-encoder` if you use `node-fetch` <= 2.x.
import fetch from "node-fetch"
const form = new FormData()
form.set("field", "Some value")
const encoder = new FormDataEncoder(form)
const options = {
method: "post",
headers: encoder.headers,
body: Readable.from(encoder)
}
await fetch("https://httpbin.org/post", options)
```
3. Sending files over form-data:
```js
import {FormData, File} from "formdata-node" // You can use `File` from fetch-blob >= 3.x
import fetch from "node-fetch"
const form = new FormData()
const file = new File(["My hovercraft is full of eels"], "file.txt")
form.set("file", file)
await fetch("https://httpbin.org/post", {method: "post", body: form})
```
4. Blobs as field's values allowed too:
```js
import {FormData, Blob} from "formdata-node" // You can use `Blob` from fetch-blob
const form = new FormData()
const blob = new Blob(["Some content"], {type: "text/plain"})
form.set("blob", blob)
// Will always be returned as `File`
let file = form.get("blob")
// The created file has "blob" as the name by default
console.log(file.name) // -> blob
// To change that, you need to set filename argument manually
form.set("file", blob, "some-file.txt")
file = form.get("file")
console.log(file.name) // -> some-file.txt
```
5. You can also append files using `fileFromPath` or `fileFromPathSync` helpers. It does the same thing as [`fetch-blob/from`](https://github.com/node-fetch/fetch-blob#blob-part-backed-up-by-filesystem), but returns a `File` instead of `Blob`:
```js
import {fileFromPath} from "formdata-node/file-from-path"
import {FormData} from "formdata-node"
import fetch from "node-fetch"
const form = new FormData()
form.set("file", await fileFromPath("/path/to/a/file"))
await fetch("https://httpbin.org/post", {method: "post", body: form})
```
6. You can still use files sourced from any stream, but unlike in v2 you'll need some extra work to achieve that:
```js
import {Readable} from "stream"
import {FormData} from "formdata-node"
class BlobFromStream {
#stream
constructor(stream, size) {
this.#stream = stream
this.size = size
}
stream() {
return this.#stream
}
get [Symbol.toStringTag]() {
return "Blob"
}
}
const content = Buffer.from("Stream content")
const stream = new Readable({
read() {
this.push(content)
this.push(null)
}
})
const form = new FormData()
form.set("stream", new BlobFromStream(stream, content.length), "file.txt")
await fetch("https://httpbin.org/post", {method: "post", body: form})
```
7. Note that if you don't know the length of that stream, you'll also need to handle form-data encoding manually or use [`form-data-encoder`](https://github.com/octet-stream/form-data-encoder) package. This is necessary to control which headers will be sent with your HTTP request:
```js
import {Readable} from "stream"
import {Encoder} from "form-data-encoder"
import {FormData} from "formdata-node"
const form = new FormData()
// You can use file-shaped or blob-shaped objects as FormData value instead of creating separate class
form.set("stream", {
type: "text/plain",
name: "file.txt",
[Symbol.toStringTag]: "File",
stream() {
return getStreamFromSomewhere()
}
})
const encoder = new Encoder(form)
const options = {
method: "post",
headers: {
"content-type": encoder.contentType
},
body: Readable.from(encoder)
}
await fetch("https://httpbin.org/post", {method: "post", body: form})
```
## Comparison
| | formdata-node | formdata-polyfill | undici FormData | form-data |
| ---------------- | ------------- | ----------------- | --------------- | -------------------- |
| .append() | ✔️ | ✔️ | ✔️ | ✔️<sup>1</sup> |
| .set() | ✔️ | ✔️ | ✔️ | ❌ |
| .get() | ✔️ | ✔️ | ✔️ | ❌ |
| .getAll() | ✔️ | ✔️ | ✔️ | ❌ |
| .forEach() | ✔️ | ✔️ | ✔️ | ❌ |
| .keys() | ✔️ | ✔️ | ✔️ | ❌ |
| .values() | ✔️ | ✔️ | ✔️ | ❌ |
| .entries() | ✔️ | ✔️ | ✔️ | ❌ |
| Symbol.iterator | ✔️ | ✔️ | ✔️ | ❌ |
| CommonJS | ✔️ | ❌ | ✔️ | ✔️ |
| ESM | ✔️ | ✔️ | ✔️<sup>2</sup> | ✔️<sup>2</sup> |
| Blob | ✔️<sup>3</sup> | ✔️<sup>4</sup> | ✔️<sup>3</sup> | ❌ |
| Browser polyfill | ❌
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
互联网产品设计与开发课程设计基于Java实现的一款AI秘书移动端应用程序+详细项目文档 (1337个子文件)
docker.asc 4KB
README.md.bak 12KB
gradlew.bat 3KB
yarn-stable-temp.cjs 2.62MB
cli 1KB
mvnw.cmd 7KB
config 59B
coverage.css 3KB
idea.min.css 2KB
Dockerfile 673B
Dockerfile 670B
软件需求规约.docx 116KB
软件架构文档.docx 79KB
软件项目计划.docx 40KB
迭代计划.docx 20KB
迭代计划.docx 19KB
迭代计划.docx 18KB
迭代评估报告.docx 18KB
.xcode.env 482B
Gemfile 365B
arrowUp.gif 91B
arrowDown.gif 89B
.gitattributes 66B
.gitignore 1KB
.gitignore 400B
.gitignore 395B
.gitignore 339B
.gitignore 176B
.gitignore 14B
.gitignore 13B
.gitignore 11B
.gitkeep 0B
build.gradle 5KB
build.gradle 547B
settings.gradle 252B
gradlew 8KB
AppDelegate.h 98B
source-1.html 7KB
source-2.html 7KB
source-1.html 6KB
index_SORT_BY_METHOD_DESC.html 6KB
index_SORT_BY_METHOD.html 6KB
index_SORT_BY_CLASS_DESC.html 6KB
index_SORT_BY_LINE_DESC.html 6KB
index_SORT_BY_CLASS.html 6KB
index_SORT_BY_NAME_DESC.html 6KB
index_SORT_BY_LINE.html 6KB
index.html 6KB
index_SORT_BY_BLOCK_DESC.html 6KB
index_SORT_BY_BLOCK.html 6KB
source-3.html 5KB
source-7.html 5KB
source-1.html 4KB
index_SORT_BY_METHOD_DESC.html 4KB
index_SORT_BY_CLASS_DESC.html 4KB
index_SORT_BY_LINE_DESC.html 4KB
index_SORT_BY_NAME_DESC.html 4KB
index_SORT_BY_BLOCK_DESC.html 4KB
index_SORT_BY_METHOD.html 4KB
index_SORT_BY_CLASS.html 4KB
index_SORT_BY_LINE.html 4KB
index_SORT_BY_BLOCK.html 4KB
index.html 4KB
source-1.html 4KB
index_SORT_BY_METHOD_DESC.html 4KB
index_SORT_BY_METHOD.html 4KB
index_SORT_BY_CLASS_DESC.html 4KB
index_SORT_BY_LINE_DESC.html 4KB
index_SORT_BY_CLASS.html 4KB
index_SORT_BY_NAME_DESC.html 4KB
index_SORT_BY_LINE.html 4KB
index.html 4KB
index_SORT_BY_BLOCK_DESC.html 3KB
index_SORT_BY_BLOCK.html 3KB
index_SORT_BY_METHOD_DESC.html 3KB
index_SORT_BY_METHOD.html 3KB
index_SORT_BY_CLASS_DESC.html 3KB
index_SORT_BY_LINE_DESC.html 3KB
index_SORT_BY_CLASS.html 3KB
index_SORT_BY_NAME_DESC.html 3KB
index_SORT_BY_LINE.html 3KB
index.html 3KB
index_SORT_BY_BLOCK_DESC.html 3KB
index_SORT_BY_BLOCK.html 3KB
source-3.html 3KB
source-2.html 3KB
source-2.html 3KB
source-5.html 3KB
index_SORT_BY_METHOD_DESC.html 3KB
index_SORT_BY_METHOD.html 3KB
index_SORT_BY_CLASS_DESC.html 3KB
index_SORT_BY_LINE_DESC.html 3KB
index_SORT_BY_CLASS.html 3KB
index_SORT_BY_NAME_DESC.html 3KB
index_SORT_BY_LINE.html 3KB
index.html 3KB
index_SORT_BY_BLOCK_DESC.html 3KB
index_SORT_BY_BLOCK.html 3KB
source-6.html 3KB
SpecialityController类的单元测试覆盖率报告.html 3KB
共 1337 条
- 1
- 2
- 3
- 4
- 5
- 6
- 14
资源评论
yanglamei1962
- 粉丝: 2474
- 资源: 797
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功