Express中最常使用的form解析中间件就是body-parser了,可是它明确表示不会支持multipart/form-data
类型的表单.javascript
因此在body-parser官方文档中提供了以下的几个支持multipart/form-data
类型的中间件的连接,或者只支持multipart/form-data
解析的中间件连接.html
名称&地址 | 周下载量 | stars |
---|---|---|
busboy | 426,278 | 1448 |
multipart | 240,921 | 993 |
formidable | 1,390,361 | 4735 |
multer | 284,926 | 5860 |
统计截止到2018年12月26日java
multer依赖busboy因此因此busboy的实际直接下载数量应该要减小28万😂.git
multipart/form-data
类型的表单?最直观的解释就是支持上传文件的form表单,若是不使用JavaScript中建立的话,显式的html声明以下:github
<form action="/profile" method="post" enctype="multipart/form-data"> <input type="file" name="file"/> <input type="submit" value="submit"> </form>
上例子中的<input type="file" name="file" >
在页面中的显示就是为一个按钮点击后能够进行文件选择.express
其次input能够添加multiple="multiple"
属性,这个时候打开的文件选择框会容许多选文件.npm
总结一下有以下几种关系:json
顺便说一句multer有中文文档.windows
enctype="multipart/form-data"
表单.multer会将上传的信息以及内容挂载到request对象上后端
const express = require('express'), multer = require('multer'), app = express();
const upload = multer({dest:'/uploads'});
注意:dest参数指定了文件输出的位置,能够详细指定文件输出以及储存后面会讲.
app.get('/',(request,response)=>{ console.log('get.request.body',request.body); console.log('get.request.file',request.file); console.log('get.request.files',request.files); response.send('<form action="/" enctype="multipart/form-data" method="post">'+ '<input type="text" name="title"><br>'+ '<input type="file" name="upload" multiple="multiple"><br>'+ '<input type="submit" value="Upload">'+ '</form>') }); app.post('/',upload.single('upload'),(request,response)=>{ console.log('post.request.body',request.body); console.log('post.request.file',request.file); console.log('post.request.files',request.files); response.redirect('/'); }); app.listen(8888,()=>{ console.log('express正在监听8888端口'); });
这个例子中咱们监听了根路径,分别处理两种不一样的请求方式,针对get咱们响应表单,针对post咱们接受上传的内容.
注意:upload.single('upload')
意思是告诉multer只接收name是upload的单个文件.
注意:这个例子中input
是能够进行多选的,也就是说后端指定了文件数量为1可是页面依然上传了多个,这个时候multer会报错.
注意:dest指定的路径为upload/
会将文件保存到根路径下的upload文件夹中,对于windows系统来讲是在运行这个应用对应的盘符下例如F:\uploads\
这个例子中我填写了一个文本内容,同时上传了一个文件,输出结果以下:
post.request.body { title: 'hello world' } post.request.file { fieldname: 'upload', originalname: '硬盘坏道扫描及修复工具Victoria.7z', encoding: '7bit', mimetype: 'application/octet-stream', destination: '/uploads', filename: '6bdfc0df998d72e6232d60f790f47ef8', path: '\\uploads\\6bdfc0df998d72e6232d60f790f47ef8', size: 1033375 }
const express = require('express'), multer = require('multer'), app = express(); const upload = multer({dest:'/uploads'}); app.get('/',(request,response)=>{ console.log('get.request.body',request.body); console.log('get.request.file',request.file); console.log('get.request.files',request.files); response.send('<form action="/" enctype="multipart/form-data" method="post">'+ '<input type="text" name="title"><br>'+ '<input type="file" name="upload"><br>'+ // 此处有两个相同name的input '<input type="file" name="upload"><br>'+ '<input type="submit" value="Upload">'+ '</form>') }); app.post('/',upload.array('upload'),(request,response)=>{ // 注意此处使用的中间件和上例中不一样 console.log('post.request.body',request.body); console.log('post.request.file',request.file); console.log('post.request.files',request.files); response.redirect('/'); }); app.listen(8888,()=>{ console.log('express正在监听8888端口'); });
在这个例子的表单中有两个同名的name都是文件类型,此次使用array的方式来进行接受,控制台输出内容以下:
post.request.body { title: 'hello world' } post.request.file undefined post.request.files [ { fieldname: 'upload', originalname: '硬盘坏道扫描及修复工具Victoria.7z', encoding: '7bit', mimetype: 'application/octet-stream', destination: '/uploads', filename: '71ed2ac4299d43a30f5c13892f33e51b', path: '\\uploads\\71ed2ac4299d43a30f5c13892f33e51b', size: 1033375 }, { fieldname: 'upload', originalname: '新建文本文档.txt', encoding: '7bit', mimetype: 'text/plain', destination: '/uploads', filename: '190bde8fcdd08d57648ffb243607ed9d', path: '\\uploads\\190bde8fcdd08d57648ffb243607ed9d', size: 218 } ]
在上面的例子中删除掉一个input,将剩余的input添加multiple
属性用于多选,页面中在选择文件框中选择多个文件也是能够顺利经过.
除了上方提到的multer.single
方法外还有其余的几种方法.
req.files
实际上它们均可以视为fields方法的包装,源码以下:
Multer.prototype.single = function (name) { return this._makeMiddleware([{ name: name, maxCount: 1 }], 'VALUE') } Multer.prototype.array = function (name, maxCount) { return this._makeMiddleware([{ name: name, maxCount: maxCount }], 'ARRAY') } Multer.prototype.fields = function (fields) { return this._makeMiddleware(fields, 'OBJECT') } Multer.prototype.none = function () { return this._makeMiddleware([], 'NONE') } Multer.prototype.any = function () { function setup () { return { limits: this.limits, preservePath: this.preservePath, storage: this.storage, fileFilter: this.fileFilter, fileStrategy: 'ARRAY' } } return makeMiddleware(setup.bind(this)) }
来自中文文档:
multer(opts)
Multer 接受一个 options 对象,其中最基本的是 dest
属性,这将告诉 Multer 将上传文件保存在哪。若是你省略 options 对象,这些文件将保存在内存中,永远不会写入磁盘。
为了不命名冲突,Multer 会修改上传的文件名。这个重命名功能能够根据您的须要定制。
如下是能够传递给 Multer 的选项。
Key | Description |
---|---|
dest or storage |
在哪里存储文件 |
fileFilter |
文件过滤器,控制哪些文件能够被接受 |
limits |
限制上传的数据 |
preservePath |
保存包含文件名的完整文件路径 |
fileFilter
设置一个函数来控制什么文件能够上传以及什么文件应该跳过,这个函数应该看起来像这样:
function fileFilter (req, file, cb) { // 这个函数应该调用 `cb` 用boolean值来 // 指示是否应接受该文件 // 拒绝这个文件,使用`false`,像这样: cb(null, false) // 接受这个文件,使用`true`,像这样: cb(null, true) // 若是有问题,你能够老是这样发送一个错误: cb(new Error('I don\'t have a clue!')) }
当遇到一个错误,multer 将会把错误发送给 express。你可使用一个比较好的错误展现页 (express标准方式)。
若是你想捕捉 multer 发出的错误,你能够本身调用中间件程序。若是你想捕捉 Multer 错误,你可使用 multer
对象下的 MulterError
类 (即 err instanceof multer.MulterError
)。
var multer = require('multer') var upload = multer().single('avatar') app.post('/profile', function (req, res) { upload(req, res, function (err) { if (err instanceof multer.MulterError) { // 发生错误 } else if (err) { // 发生错误 } // 一切都好 }) })
DiskStorage
)磁盘存储引擎可让你控制文件的存储。
var storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, '/tmp/my-uploads') }, filename: function (req, file, cb) { cb(null, file.fieldname + '-' + Date.now()) } }) var upload = multer({ storage: storage })
有两个选项可用,destination
和 filename
。他们都是用来肯定文件存储位置的函数。
destination
是用来肯定上传的文件应该存储在哪一个文件夹中。也能够提供一个 string
(例如 '/tmp/uploads'
)。若是没有设置 destination
,则使用操做系统默认的临时文件夹。
注意: 若是你提供的 destination
是一个函数,你须要负责建立文件夹。当提供一个字符串,multer 将确保这个文件夹是你建立的。
filename
用于肯定文件夹中的文件名的肯定。 若是没有设置 filename
,每一个文件将设置为一个随机文件名,而且是没有扩展名的。
注意: Multer 不会为你添加任何扩展名,你的程序应该返回一个完整的文件名。
每一个函数都传递了请求对象 (req
) 和一些关于这个文件的信息 (file
),有助于你的决定。
注意 req.body
可能尚未彻底填充,这取决于向客户端发送字段和文件到服务器的顺序。
MemoryStorage
)内存存储引擎将文件存储在内存中的 Buffer
对象,它没有任何选项。
var storage = multer.memoryStorage() var upload = multer({ storage: storage })
当使用内存存储引擎,文件信息将包含一个 buffer
字段,里面包含了整个文件数据。
警告: 当你使用内存存储,上传很是大的文件,或者很是多的小文件,会致使你的应用程序内存溢出。
const express = require('express'), multer = require('multer'), app = express(); const storage = multer.diskStorage({ destination:__dirname, // 保存到当前目录 filename(request,file,callback){ console.log('filename:',file); callback(null,'newfilename');// 修改上传的文件名称 } }); const upload = multer({ dest:'/uploads', fileFilter(request,file,cb){ console.log('fileFilter:',file); cb(null,true); }, limits:{ fileSize:100000 // 限制上传文件大小为100000字节 }, storage // 使用默认的储存器 });
最后触发的顺序为: