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 相关文章推荐
js自带函数备忘 数组
Dec 29 Javascript
juqery 学习之三 选择器 可见性 元素属性
Nov 25 Javascript
JavaScript中变量提升 Hoisting
Jul 03 Javascript
JavaScript中property和attribute的区别详细介绍
Mar 03 Javascript
使用基于Node.js的构建工具Grunt来发布ASP.NET MVC项目
Feb 15 Javascript
Bootstrap导航条鼠标悬停下拉菜单
Jan 04 Javascript
AngularJS select加载数据选中默认值的方法
Feb 28 Javascript
electron 安装,调试,打包的具体使用
Nov 06 Javascript
Vue中qs插件的使用详解
Feb 07 Javascript
从零开始用webpack构建一个vue3.0项目工程的实现
Sep 24 Javascript
JavaScript大数相加相乘的实现方法实例
Oct 18 Javascript
详解vue-router的导航钩子(导航守卫)
Nov 02 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
并发下常见的加锁及锁的PHP具体实现代码
2010/10/12 PHP
codeigniter中测试通过的分页类示例
2014/04/17 PHP
php中文繁体和简体相互转换的方法
2015/03/21 PHP
Symfony的安装和配置方法
2016/03/17 PHP
比较简单的异步加载JS文件的代码
2009/07/18 Javascript
jQuery学习7 操作JavaScript对象和集合的函数
2010/02/07 Javascript
利用JavaScript检测CPU使用率自己写的
2014/03/22 Javascript
jquery实现仿Flash的横向滑动菜单效果代码
2015/09/17 Javascript
AngularJS控制器controller正确的通信的方法
2016/01/25 Javascript
jQuery on()绑定动态元素出现的问题小结
2016/02/19 Javascript
Bootstrap实现登录校验表单(带验证码)
2016/06/23 Javascript
JS中如何比较两个Json对象是否相等实例代码
2016/07/13 Javascript
Node.js中如何合并两个复杂对象详解
2016/12/31 Javascript
JavaScript 函数节流详解及方法总结
2017/02/09 Javascript
JavaScript数据结构之数组的表示方法示例
2017/04/12 Javascript
webpack4 CSS Tree Shaking的使用
2018/09/03 Javascript
Vue中使用vux配置代码详解
2018/09/16 Javascript
python多进程中的内存复制(实例讲解)
2018/01/05 Python
python如何实现反向迭代
2018/03/20 Python
使用Python监控文件内容变化代码实例
2018/06/04 Python
Python中pandas模块DataFrame创建方法示例
2018/06/20 Python
python消费kafka数据批量插入到es的方法
2018/12/27 Python
Python 装饰器@,对函数进行功能扩展操作示例【开闭原则】
2019/10/17 Python
TensorFlow实现指数衰减学习率的方法
2020/02/05 Python
Python中Pyspider爬虫框架的基本使用详解
2021/01/27 Python
Kenneth Cole官网:纽约时尚优雅品牌
2016/11/14 全球购物
ECCO英国官网:丹麦鞋履品牌
2019/09/03 全球购物
JavaScript实现前端网页版倒计时
2021/03/24 Javascript
工商企业管理实习自我鉴定
2013/12/04 职场文书
简历的自我评价范文
2014/02/04 职场文书
名企HR怎样看待求职信
2014/02/23 职场文书
领导班子对照检查剖析材料
2014/10/13 职场文书
2015年国庆放假通知范文
2015/08/18 职场文书
写自招自荐信的绝招!
2019/04/19 职场文书
Nginx快速入门教程
2021/03/31 Servers
这样写python注释让代码更加的优雅
2021/06/02 Python