Express文件表单剖析中间件 Multer简介

媒介

Express中最常运用的form剖析中间件就是body-parser了,然则它明白示意不会支撑multipart/form-data范例的表单.

所以在body-parser官方文档中供应了以下的几个支撑multipart/form-data范例的中间件的链接,或许只支撑multipart/form-data剖析的中间件链接.

称号&地点周下载量stars
busboy426,2781448
multipart240,921993
formidable1,390,3614735
multer284,9265860

统计截止到2018年12月26日

multer依靠busboy所以所以busboy的现实直接下载数目应当要削减28万😂.

什么是multipart/form-data范例的表单?

最直观的诠释就是支撑上传文件的form表单,假如不运用JavaScript中建立的话,显式的html声明以下:

<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" >在页面中的显现就是为一个按钮点击后能够举行文件挑选.

其次input能够增加multiple="multiple"属性,这个时刻翻开的文件挑选框会许可多选文件.

总结一下有以下几种关联:

  • 一个name对应多个文件
  • 一个name对应一个文件
  • 多个name对应多个单个文件
  • 多个name对应多个文件

趁便说一句multer有中文文档.

正文

特性

  • multer只会剖析form设置为enctype="multipart/form-data"表单.
  • multer能够定制存储引擎
  • multer会将上传的信息以及内容挂载到request对象上

    • request.body 保存文本内容
    • request.file 保存单个文件信息以及对应内容(内存存储形式)
    • request.files 保存多个文件信息以及对应的内容(内存存储形式)

基础事情流程

  1. 建立一个multer实例
  2. 运用该实例上供应的差别要领猎取差别功用的中间件
  3. 放入到对应的路由中

上传单个文件实例

引入multer和Express

const
    express = require('express'),
    multer = require('multer'),
    app = express();

传入设置参数

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

注重:dest参数指定了文件输出的位置,能够细致指定文件输出以及贮存背面会讲.

运用multer中间件通报单个文件

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要领外另有其他的几种要领.

  • array(name:string,maxcount?:number) 依据name限定上传文件的最大个数
  • fields(fields:object) 自定义限定划定规矩
  • none() 只保存文本信息
  • any() 许可恣意范例经由过程,文件数组将保存在 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))
}

经常使用API一览

来自中文文档:

multer(opts)

Multer 吸收一个 options 对象,个中最基础的是 dest 属性,这将通知 Multer 将上传文件保存在哪。假如你省略 options 对象,这些文件将保存在内存中,永久不会写入磁盘。

为了防止定名争执,Multer 会修正上传的文件名。这个重定名功用能够依据您的须要定制。

以下是能够通报给 Multer 的选项。

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

有两个选项可用,destinationfilename。他们都是用来肯定文件存储位置的函数。

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 字段,内里包括了全部文件数据。

正告: 当你运用内存存储,上传异常大的文件,或许异常多的小文件,会致使你的运用递次内存溢出。

filefilter和filename另有路由触发的递次

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 // 运用默许的贮存器
});

末了触发的递次为:

  1. filefilter
  2. filename
  3. 我们定义的路由
    原文作者:ASCll
    原文地址: https://segmentfault.com/a/1190000017521702
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞