express文件上传中间件Multer详解


Posted in Javascript onOctober 24, 2016

前言

Express默认并不处理HTTP请求体中的数据,对于普通请求体(JSON、二进制、字符串)数据,可以使用body-parser中间件。而文件上传(multipart/form-data请求),可以基于请求流处理,也可以使用formidable模块或Multer中间件。

1. multer中间件

Multer是Express官方推出的,用于Node.jsmultipart/form-data请求数据处理的中间件。

它基于busboy构建,可以高效的处理文件上传,但并不处理multipart/form-data之外的用户请求。

2. 安装

npm install multer --save

3. 使用

Multer在解析完请求体后,会向Request对象中添加一个body对象和一个file或files对象(上传多个文件时使用files对象 )。其中,body对象中包含所提交表单中的文本字段(如果有),而file(或files)对象中包含通过表单上传的文件。

基本使用示例如下:

var express = require('express')
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })

var app = express()

app.post('/profile', upload.single('avatar'), function (req, res, next) {
 // req.file 是 `avatar` 文件
 // req.body 对象中是表单中提交的文本字段(如果有)
})

app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
 // req.files 是 `photos` 文件数组
 // req.body 对象中是表单中提交的文本字段(如果有)
})

var cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
app.post('/cool-profile', cpUpload, function (req, res, next) {
 // req.files 是一个对象 (String -> Array),文件的字段名是其 key,文件数组是 key的值
 //
 // 如:
 // req.files['avatar'][0] -> File
 // req.files['gallery'] -> Array
 //
 // req.body 对象中是表单中提交的文本字段(如果有)
})

在使用中,如果仅需要处理multipart表单中的文本字段,可以使用multer中的.single() .array()fields()方法。

如,可以像下面这样使用.array()方法:

var express = require('express')
var app = express()
var multer = require('multer')
var upload = multer()

app.post('/profile', upload.array(), function (req, res, next) {
 // req.body 中包含文本字段
})

4. multer的API

4.1 文件对象

multer解析完上传文件后,会被保存为一个包含以下字段的对象:

       fieldname - 表单提交的文件名(input控件的name属性)

       originalname - 文件在用户设备中的原始名称

       encoding - 文件的编码类型

       mimetype - 文件的Mime类型

       size - 文件的大小

       destination - 文件的保存目录(DiskStorage)

       filename - 文件在destination中的名称(DiskStorage)

       path - 上传文件的全路径(DiskStorage)

       buffer - 文件对象的Buffer(MemoryStorage)

4.2 方法

multer(opts) - 创建对象

引用multer模块后,我们会获取到一个顶级方法。该方法是一个工厂函数,可以使用这个方法创建Multer对象。它接受一个选项对象,最基本的选项是dest,它告诉 Multer 文件的存储位置。如果忽略该选项,文件会被保存在内存中,并且永远不会写入硬盘中。

默认情况下,Multer会对文件进行重命令,以避免名称冲突。重命名函数,可以按需要自定义。

Multer的选项对象中可以包含以下值:

       dest或storage - 文件存储位置

       fileFilter - 函数,控制可上传的文件类型

       limits - 上传数据限制(文件大小)

在一般的Web应用中,只有dest选项需要设置。使用示例如下:

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

如果需要对上传文件做更多控制,可以使用storage代替dest,Multer会将存储引擎由DiskStorage(硬盘存储)切换为MemoryStorage(内存存储)。

创建multer对象后,我们可以使用以下实例来接收上传文件:

.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'错误。这个方法与upload.fields([])类似。

.any() - 接收所有文件

接收请求中的所有文件。上传文件数组会被保存在req.files中。

4.3 选项参数

storage - 存储引擎

该选项有以下两个可选项:

       DiskStorage - 硬盘存储

       MemoryStorage - 内存存储

.diskStorage(obj)与硬盘存储

硬盘存储引擎提供了将文件存储到磁盘的完全控制:

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

.diskStorage()方法提供了文件存储位置控制权限,该方法接收一个对象参数,其中包含两destination和filename两个属性。

destination用于设置文件的存储目录,可以是一个函数或字符串。若未提供该参数,将使用系统的临时目录。

filename用于设置文件名。若未提供该参数,将使用一个随机字符串,且文件名中不包含扩展名。

.memoryStorage()与内存存储

内存存储引擎会以Buffer的形式将文件保存在内存中。该方法没有任何参数:

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

limits - 文件尺寸

该选项用于设置文件尺寸,Multer 会将这个对象传递至busboy中。limits对象中可以包含以下可选值:

       fieldNameSize - 字段名最大尺寸。默认值:100 bytes

       fieldSize - 字段值最大尺寸。默认值:1MB

       fields - 非文件字段的最大数量。默认值:Infinity

       fileSize - multipart 表单中,文件的最大尺寸。默认值:Infinity

       files - multipart 表单中,文件最大数量。默认值:Infinity

       parts - multipart 表单中,最大组件(fields+files)数量。默认值:Infinity

       headerPairs - 默认值:2000

fileFilter - 文件筛选

fileFilter用于控制要哪些文件是可接受的,哪些是要被拒绝的。使用形式如下:

function fileFilter (req, file, cb) {

 // 需要调用回调函数 `cb`,
 // 并在第二个参数中传入一个布尔值,用于指示文件是否可接受

 // 如果要拒绝文件,上传则传入 `false`。如:
 cb(null, false)

 // 如果接受上传文件,则传入 `true`。如:
 cb(null, true)

 // 出错后,可以在第一个参数中传入一个错误:
 cb(new Error('I don\'t have a clue!'))
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
javascript级联下拉列表实例代码(自写)
May 10 Javascript
js控制表单操作的常用代码小结
Aug 15 Javascript
div+css+js实现无缝滚动类似marquee无缝滚动兼容firefox
Aug 29 Javascript
使用js显示当前时间示例
Mar 02 Javascript
使用jquery.qrcode生成彩色二维码实例
Aug 08 Javascript
jquery实现点击向下展开菜单项(伸缩导航)效果
Aug 22 Javascript
js表单中选择框值的获取及表单的序列化
Dec 17 Javascript
关于JavaScript中forEach和each用法浅析
Jul 27 Javascript
vue 修改 data 数据问题并实时显示的方法
Aug 27 Javascript
vue插件实现v-model功能
Sep 10 Javascript
解决iview多表头动态更改列元素发生的错误的方法
Nov 02 Javascript
vue递归获取父元素的元素实例
Aug 07 Javascript
用js实现博客打赏功能
Oct 24 #Javascript
jQuery autoComplete插件两种使用方式及动态改变参数值的方法详解
Oct 24 #Javascript
jQuery插件实现可输入和自动匹配的下拉框
Oct 24 #Javascript
JS中split()用法(将字符串按指定符号分割成数组)
Oct 24 #Javascript
在js中实现邮箱格式的验证方法(推荐)
Oct 24 #Javascript
js实现上传文件添加和删除文件选择框
Oct 24 #Javascript
JS取数字小数点后两位或n位的简单方法
Oct 24 #Javascript
You might like
cmd下运行php脚本
2008/11/25 PHP
PHP 字符串加密函数(在指定时间内加密还原字符串,超时无法还原)
2010/04/28 PHP
PHP+JS实现大规模数据提交的方法
2015/07/02 PHP
jQuery使用手册之 事件处理
2007/03/24 Javascript
JavaScript 字符串连接性能优化
2008/12/20 Javascript
jQuery+css+html实现页面遮罩弹出框
2013/03/21 Javascript
论Bootstrap3和Foundation5网格系统的异同
2016/05/16 Javascript
跨域请求的完美解决方法(JSONP, CORS)
2016/06/12 Javascript
妙用Bootstrap的 popover插件实现校验表单提示功能
2016/08/29 Javascript
jQuery为某个div加入行样式
2017/06/09 jQuery
详解Webpack DLL用法以及功能
2017/07/11 Javascript
通过button将form表单的数据提交到action层的实例
2017/09/08 Javascript
微信小程序实现红包功能(后端PHP实现逻辑)
2018/07/11 Javascript
vue-cli3.0如何使用CDN区分开发、生产、预发布环境
2018/11/22 Javascript
JavaScript实现的3D旋转魔方动画效果实例代码
2019/07/31 Javascript
Javascript 关于基本类型和引用类型的个人理解
2019/11/01 Javascript
Vue中computed和watch有哪些区别
2020/12/19 Vue.js
使用python解析xml成对应的html示例分享
2014/04/02 Python
python中文编码问题小结
2014/09/28 Python
浅析Python中的多条件排序实现
2016/06/07 Python
对python抓取需要登录网站数据的方法详解
2018/05/21 Python
django2.0扩展用户字段示例
2019/02/13 Python
Python使用字典的嵌套功能详解
2019/02/27 Python
pytorch 更改预训练模型网络结构的方法
2019/08/19 Python
html5嵌入内容_动力节点Java学院整理
2017/07/07 HTML / CSS
使用html5新特性轻松监听任何App自带返回键的示例
2018/03/13 HTML / CSS
韩国三大免税店之一:THE GRAND 中文免税店
2016/07/21 全球购物
Sunglasses Shop德国站:欧洲排名第一的太阳镜网站
2017/08/01 全球购物
如何写出高质量、高性能的MySQL查询
2014/11/17 面试题
市场营销求职信范文
2014/02/21 职场文书
餐厅总厨求职信
2014/03/04 职场文书
计算机科学系职业生涯规划书
2014/03/08 职场文书
班主任高考寄语
2015/02/26 职场文书
贫民窟的百万富翁观后感
2015/06/09 职场文书
vue引入Excel表格插件的方法
2021/04/28 Vue.js
Python多个MP4合成视频的实现方法
2021/07/16 Python