🌐 Nodejs.cn

multer 中间件

Multer 是一个用于处理 multipart/form-data 的 node.js 中间件,主要用于文件上传。它是基于 busboy 编写的,以实现最大的效率。

🌐 Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files. It is written on top of busboy for maximum efficiency.

注意:Multer 不会处理任何非 multipart (multipart/form-data) 的表单。

翻译

🌐 Translations

此自述文件也提供其他语言版本:

🌐 This README is also available in other languages:

العربية阿拉伯语
简体中文中文
Français法语
한국어韩语
Português葡萄牙语(巴西)
Русский язык俄语
Español西班牙语
O’zbek tili乌兹别克语
Việt Nam越南语
Türkçe土耳其语

安装

🌐 Installation

Terminal window
npm install multer

Note

multer 不包含其自身的 TypeScript 类型定义。如果你使用 TypeScript,还需要作为开发依赖从 DefinitelyTyped 安装社区维护的类型:

Terminal window
npm install --save-dev @types/multer

使用

🌐 Usage

Multer 向 request 对象添加一个 body 对象和一个 filefiles 对象。body 对象包含表单中文本字段的值,filefiles 对象包含通过表单上传的文件。

🌐 Multer adds a body object and a file or files object to the request object. The body object contains the values of the text fields of the form, the file or files object contains the files uploaded via the form.

基本使用示例:

🌐 Basic usage example:

别忘了在你的表格中填写 enctype="multipart/form-data"

🌐 Don’t forget the enctype="multipart/form-data" in your form.

<form action="/profile" method="post" enctype="multipart/form-data">
<input type="file" name="avatar" />
</form>
const express = require('express');
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
const app = express();
app.post('/profile', upload.single('avatar'), function (req, res, next) {
// req.file is the `avatar` file
// req.body will hold the text fields, if there were any
});
app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
// req.files is array of `photos` files
// req.body will contain the text fields, if there were any
});
const uploadMiddleware = upload.fields([
{ name: 'avatar', maxCount: 1 },
{ name: 'gallery', maxCount: 8 },
]);
app.post('/cool-profile', uploadMiddleware, function (req, res, next) {
// req.files is an object (String -> Array) where fieldname is the key, and the value is array of files
//
// e.g.
// req.files['avatar'][0] -> File
// req.files['gallery'] -> Array
//
// req.body will contain the text fields, if there were any
});

如果你需要处理仅包含文本的多部分表单,你应该使用 .none() 方法:

🌐 In case you need to handle a text-only multipart form, you should use the .none() method:

const express = require('express');
const app = express();
const multer = require('multer');
const upload = multer();
app.post('/profile', upload.none(), function (req, res, next) {
// req.body contains the text fields
});

这里有一个关于如何在 HTML 表单中使用 multer 的示例。特别注意 enctype="multipart/form-data"name="uploaded_file" 字段:

🌐 Here’s an example on how multer is used in a HTML form. Take special note of the enctype="multipart/form-data" and name="uploaded_file" fields:

<form action="/stats" enctype="multipart/form-data" method="post">
<div class="form-group">
<input type="file" class="form-control-file" name="uploaded_file" />
<input type="text" class="form-control" placeholder="Number of speakers" name="nspeakers" />
<input type="submit" value="Get me the stats!" class="btn btn-default" />
</div>
</form>

然后在你的 JavaScript 文件中,你需要添加这些行来访问文件和主体。在上传函数中使用表单中的 name 字段值非常重要。这会告诉 multer 应该在请求的哪个字段中查找文件。如果 HTML 表单和服务器上的这些字段不一样,你的上传将会失败:

🌐 Then in your javascript file you would add these lines to access both the file and the body. It is important that you use the name field value from the form in your upload function. This tells multer which field on the request it should look for the files in. If these fields aren’t the same in the HTML form and on your server, your upload will fail:

const multer = require('multer');
const upload = multer({ dest: './public/data/uploads/' });
app.post('/stats', upload.single('uploaded_file'), function (req, res) {
// req.file is the name of your file in the form above, here 'uploaded_file'
// req.body will hold the text fields, if there were any
console.log(req.file, req.body);
});

API

文件信息

🌐 File information

每个文件包含以下信息:

🌐 Each file contains the following information:

描述备注
fieldname表单中指定的字段名称
originalname用户计算机上的文件名称
encoding文件的编码类型
mimetype文件的 Mime 类型
size文件的字节大小
destination文件已保存的文件夹DiskStorage
filenamedestination 中的文件名称DiskStorage
path上传文件的完整路径DiskStorage
buffer整个文件的 BufferMemoryStorage

multer(opts)

Multer 接受一个选项对象,其中最基本的是 dest 属性,它告诉 Multer 将文件上传到哪里。如果你省略选项对象,文件将保存在内存中,永远不会写入磁盘。

🌐 Multer accepts an options object, the most basic of which is the dest property, which tells Multer where to upload the files. In case you omit the options object, the files will be kept in memory and never written to disk.

默认情况下,Multer 会重命名文件以避免命名冲突。重命名功能可以根据你的需求进行自定义。

🌐 By default, Multer will rename the files so as to avoid naming conflicts. The renaming function can be customized according to your needs.

以下是可以传递给 Multer 的选项。

🌐 The following are the options that can be passed to Multer.

描述
deststorage存储文件的位置
fileFilter控制哪些文件被接受的功能
limits上传数据的限制
preservePath保留文件的完整路径而不仅仅是基本名称
defParamCharset对于不是扩展参数(包含显式字符集)的部分头参数(例如文件名)的值使用的默认字符集。默认值:'latin1'

在一个普通的网络应用中,可能只需要 dest,并按如下示例进行配置。

🌐 In an average web app, only dest might be required, and configured as shown in the following example.

const upload = multer({ dest: 'uploads/' });

如果你想对你的上传有更多控制,你会想使用 storage 选项而不是 dest。Multer 提供了存储引擎 DiskStorageMemoryStorage;更多引擎可以从第三方获得。

🌐 If you want more control over your uploads, you’ll want to use the storage option instead of dest. Multer ships with storage engines DiskStorage and MemoryStorage; More engines are available from third parties.

.single(fieldname)

接受名为 fieldname 的单个文件。该单个文件将存储在 req.file 中。

🌐 Accept a single file with the name fieldname. The single file will be stored in req.file.

.array(fieldname[, maxCount])

接受一个文件数组,所有文件名都为 fieldname。如果上传的文件超过 maxCount,可以选择报错。文件数组将存储在 req.files

🌐 Accept an array of files, all with the name fieldname. Optionally error out if more than maxCount files are uploaded. The array of files will be stored in req.files.

.fields(fields)

接受由 fields 指定的多种文件。包含文件数组的对象将存储在 req.files 中。

🌐 Accept a mix of files, specified by fields. An object with arrays of files will be stored in req.files.

fields 应该是包含 name 和可选 maxCount 的对象数组。 示例:

[
{ name: 'avatar', maxCount: 1 },
{ name: 'gallery', maxCount: 8 },
];

.none()

仅接受文本字段。如果上传任何文件,将返回错误代码“LIMIT_UNEXPECTED_FILE”。

🌐 Accept only text fields. If any file upload is made, error with code “LIMIT_UNEXPECTED_FILE” will be issued.

.any()

接受通过网络传输的所有文件。文件数组将存储在req.files中。

🌐 Accepts all files that comes over the wire. An array of files will be stored in req.files.

警告: 确保你始终处理用户上传的文件。
切勿将 multer 添加为全局中间件,因为恶意用户可能会向你未预料的路由上传文件。
仅在你处理上传文件的路由上使用此功能。

storage

DiskStorage

磁盘存储引擎使你能够完全控制将文件存储到磁盘上。

🌐 The disk storage engine gives you full control on storing files to disk.

const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/tmp/my-uploads');
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
cb(null, file.fieldname + '-' + uniqueSuffix);
},
});
const upload = multer({ storage: storage });

有两个可用选项,destinationfilename。它们都是决定文件应存储位置的函数。

🌐 There are two options available, destination and filename. They are both functions that determine where the file should be stored.

destination 用于确定上传的文件应存储在哪个文件夹中。也可以将其作为 string(例如 '/tmp/uploads')提供。如果未提供 destination,则使用操作系统的临时文件默认目录。

注意: 当你以函数形式提供 destination 时,你负责创建目录。当传递字符串时,multer 会确保为你创建目录。

filename 用于确定文件在文件夹中的命名。如果没有提供 filename,每个文件都会被赋予一个不包含任何文件扩展名的随机名称。

注意: Multer 不会为你附加任何文件扩展名,你的函数应返回带有完整文件扩展名的文件名。

每个函数都会传递请求(req)以及一些关于文件的信息(file)以帮助做出决策。

🌐 Each function gets passed both the request (req) and some information about the file (file) to aid with the decision.

请注意,req.body 可能尚未完全填充。这取决于客户端向服务器传输字段和文件的顺序。

🌐 Note that req.body might not have been fully populated yet. It depends on the order that the client transmits fields and files to the server.

要了解回调中使用的调用约定(需要将 null 作为第一个参数传递),请参阅 Node.js 错误处理

🌐 For understanding the calling convention used in the callback (needing to pass null as the first param), refer to Node.js error handling

MemoryStorage

内存存储引擎将文件作为 Buffer 对象存储在内存中。它没有任何选项。

🌐 The memory storage engine stores the files in memory as Buffer objects. It doesn’t have any options.

const storage = multer.memoryStorage();
const upload = multer({ storage: storage });

在使用内存存储时,文件信息将包含一个名为buffer的字段,该字段包含整个文件。

🌐 When using memory storage, the file info will contain a field called buffer that contains the entire file.

警告:上传非常大的文件,或在短时间内上传大量相对较小的文件,可能会导致在使用内存存储时,你的应用内存耗尽。

limits

一个对象,用于指定以下可选属性的大小限制。Multer 会将此对象直接传入 busboy,属性的详细信息可以在 busboy 的页面 上找到。

🌐 An object specifying the size limits of the following optional properties. Multer passes this object into busboy directly, and the details of the properties can be found on busboy’s page.

以下整数值可用:

🌐 The following integer values are available:

描述默认值
fieldNameSize最大字段名长度100 字节
fieldSize最大字段值长度(以字节为单位)1MB
fields非文件字段的最大数量无限
fileSize对于多部分表单,最大文件大小(以字节为单位)无限
files对于多部分表单,文件字段的最大数量无限
parts对于多部分表单,部分(字段 + 文件)的最大数量无限
headerPairs对于多部分表单,解析的最大头键=>值对数量2000
fieldNestingDepth字段名的最大嵌套层级(例如 a[b][c] 有 2 层)无限

指定限制可以帮助保护你的网站免受拒绝服务(DoS)攻击。

🌐 Specifying the limits can help protect your site against denial of service (DoS) attacks.

fileFilter

将此设置为一个函数,以控制应上传哪些文件以及应跳过哪些文件。该函数应如下所示:

🌐 Set this to a function to control which files should be uploaded and which should be skipped. The function should look like this:

function fileFilter(req, file, cb) {
// The function should call `cb` with a boolean
// to indicate if the file should be accepted
// To reject this file pass `false`, like so:
cb(null, false);
// To accept the file pass `true`, like so:
cb(null, true);
// You can always pass an error if something goes wrong:
cb(new Error("I don't have a clue!"));
}

安全

🌐 Security

指定限制可以帮助保护你的站点免受拒绝服务(DoS)攻击。对于大多数应用,建议使用以下限制:

🌐 Specifying the limits can help protect your site against denial of service (DoS) attacks. The following limits are recommended for most applications:

  • fileSize — 设置为你使用场景中预期的最大文件大小
  • files — 设置为每个请求的最大文件数量
  • fields — 设置为每个请求的最大文本字段数
  • fieldNestingDepth — 设置为字段名所需的最小深度(例如 a[b][c] 对应 3

错误处理

🌐 Error handling

遇到错误时,Multer 会将错误委托给 Express。你可以使用 标准的 Express 方式 显示一个漂亮的错误页面。

🌐 When encountering an error, Multer will delegate the error to Express. You can display a nice error page using the standard express way.

如果你想专门捕获来自 Multer 的错误,你可以自己调用中间件函数。此外,如果你只想捕获 Multer 错误,你可以使用附加到 multer 对象本身的 MulterError 类(例如 err instanceof multer.MulterError)。

🌐 If you want to catch errors specifically from Multer, you can call the middleware function by yourself. Also, if you want to catch only the Multer errors, you can use the MulterError class that is attached to the multer object itself (e.g. err instanceof multer.MulterError).

const multer = require('multer');
const upload = multer().single('avatar');
app.post('/profile', function (req, res) {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
// A Multer error occurred when uploading.
} else if (err) {
// An unknown error occurred when uploading.
}
// Everything went fine.
});
});

自定义存储引擎

🌐 Custom storage engine

有关如何构建自己的存储引擎的信息,请参阅 Multer Storage Engine

🌐 For information on how to build your own storage engine, see Multer Storage Engine.

许可证

🌐 License

MIT