黑人的命也是命。
支持平等正义倡议.

Multer 构建状态 NPM 版本 js-standard-style

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

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

翻译

此 README 也提供其他语言版本

安装

$ npm install --save multer

用法

Multer 将一个 body 对象和一个 filefiles 对象添加到 request 对象中。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 cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
app.post('/cool-profile', cpUpload, 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() 方法

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" 字段

<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 内存存储

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 作为全局中间件添加,因为恶意用户可能会将文件上传到你没有预料到的路由。仅在处理上传文件的路由上使用此函数。

storage

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 错误处理

内存存储

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

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

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

警告:上传非常大的文件,或在使用内存存储时,以非常快的速度上传大量相对较小的文件,会导致您的应用程序内存不足。

limits

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

以下整数可用

描述 默认
fieldNameSize 最大字段名称大小 100 字节
fieldSize 最大字段值大小(以字节为单位) 1MB
fields 非文件字段的最大数量 无穷大
fileSize 对于多部分表单,最大文件大小(以字节为单位) 无穷大
files 对于多部分表单,最大文件字段数量 无穷大
parts 对于多部分表单,最大部分数量(字段 + 文件) 无穷大
headerPairs 对于多部分表单,要解析的最大标头键值对数量 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