注意

此页面由 multer README 生成。

Multer NPM 版本 NPM 下载量 构建状态 测试覆盖率 OpenSSF 记分卡徽章

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

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

翻译

此 README 也有其他语言版本

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

安装

$ npm install multer

用法

Multer 会在 request 对象上添加一个 body 对象以及一个 filefiles 对象。body 对象包含表单文本字段的值,filefiles 对象包含通过表单上传的文件。

基本用法示例

不要忘记在表单中添加 enctype="multipart/form-data"

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

如果你需要处理一个纯文本的 multipart 表单,你应该使用 .none() 方法

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

以下是 Multer 在 HTML 表单中的使用示例。请特别注意 enctype="multipart/form-data"name="uploaded_file" 字段

<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 表单和服务器上的这些字段不一致,你的上传将会失败

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

文件信息

每个文件包含以下信息

描述 注意
fieldname 表单中指定的字段名  
originalname 用户计算机上的文件名  
encoding 文件的编码类型  
mimetype 文件的 MIME 类型  
size 文件大小(字节)  
destination 文件保存到的文件夹 DiskStorage
filename 文件在 destination 中的名称 DiskStorage
path 上传文件的完整路径 DiskStorage
buffer 整个文件的 Buffer MemoryStorage

multer(opts)

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

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

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

描述
deststorage 文件存储位置
fileFilter 控制哪些文件被接受的函数
limits 上传数据的限制
preservePath 保留文件的完整路径而不是只保留基本名称

在普通的 Web 应用中,可能只需要 dest,并按以下示例所示进行配置。

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

如果你希望对上传有更多控制,你会希望使用 storage 选项而不是 dest。Multer 内置了存储引擎 DiskStorageMemoryStorage;更多引擎可从第三方获取。

.single(fieldname)

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

.array(fieldname[, maxCount])

接受一个文件数组,所有文件都名为 fieldname。如果上传的文件数量超过 maxCount,可选地抛出错误。文件数组将存储在 req.files 中。

.fields(fields)

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

fields 应该是一个对象数组,每个对象包含 name 属性和可选的 maxCount 属性。例如

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

.none()

只接受文本字段。如果进行任何文件上传,将发出代码为 “LIMIT_UNEXPECTED_FILE” 的错误。

.any()

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

警告:请确保你总是处理用户上传的文件。切勿将 Multer 添加为全局中间件,因为恶意用户可能会将文件上传到你未预期的路由。仅在处理上传文件的路由上使用此函数。

存储

DiskStorage

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

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。它们都是确定文件存储位置的函数。

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

注意:当将 destination 作为函数提供时,你有责任创建目录。当传递字符串时,Multer 将确保为你创建目录。

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

注意:Multer 不会为你添加任何文件扩展名,你的函数应该返回一个包含文件扩展名的完整文件名。

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

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

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

MemoryStorage

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

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

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

警告:当使用内存存储时,上传非常大的文件,或者非常快速地上传大量相对较小的文件,可能会导致你的应用程序内存耗尽。

limits

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

以下整数值可用

描述 默认值
fieldNameSize 最大字段名大小 100 字节
fieldSize 最大字段值大小(字节) 1MB
fields 最大非文件字段数 无限
fileSize 对于 multipart 表单,最大文件大小(字节) 无限
files 对于 multipart 表单,最大文件字段数 无限
parts 对于 multipart 表单,最大部件数(字段 + 文件) 无限
headerPairs 对于 multipart 表单,要解析的最大 header key=>value 对数 2000

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

fileFilter

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

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!'))

}

错误处理

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

如果你想专门捕获来自 Multer 的错误,你可以自己调用中间件函数。此外,如果你只想捕获 Multer 错误,你可以使用附加在 multer 对象本身的 MulterError 类(例如 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.
  })
})

自定义存储引擎

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

许可证

MIT