使用Node.js中间件Multer与Express框架实现文件上传功能接口

什么是Multer?

Multer是一个Node.js中间件,用于处理 multipart/form-data类型的表单数据,它主要用于上传文件。它是写在busboy之上非常高效。

注意: Multer不会处理任何非multipart/form-data类型的表单数据。

如何安装?

$ npm install --save multer

怎么使用?

Multer 会添加一个body对象以及file或files对象到express的request对象中。body对象包含表单的文本域信息,file或files对象包含对象表单上传的文件信息。

基本使用方法:

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

app.post('/upload', upload.single('file'), function (req, res, next) {
  // req.file 是file文件的信息
  // req.body 将具有文本域数据,如果存在的话
})

app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
  // req.files 是photos文件数组的信息
  // req.body 将具有文本域数据,如果存在的话
})

const cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
app.post('/cool-profile', cpUpload, function (req, res, next) {
  // req.files 是一个对象 (String -> Array) 键是文件名,值是文件数组
  //
  // 例如:
  //  req.files['avatar'][0] -> File
  //  req.files['gallery'] -> Array
  //
  // req.body 将具有文本域数据,如果存在的话
})

Multer API

KeyDescriptionNote
fieldnameField name 由表单指定
originalname用户计算机上的文件的名称
encoding文件编码
mimetype文件的 MIME 类型
size文件大小(字节单位)
destination保存路径DiskStorage
filename保存在destination中的文件名DiskStorage
path已上传文件的完整路径DiskStorage
buffer一个存放了整个文件的BufferMemoryStorage

Multer(opts) 参数

Multer 接受一个options对象,其中最基本的是dest属性,这将告诉Multer将上传文件保存在哪。如果你省略options对象,这些文件将保存在内存中,永远不会写入磁盘。

为了避免命名冲突,Multer 会修改上传的文件名。这个重命名功能可以根据您的需要定制。

以下是可以传递给 Multer 的选项。

KeyDescription
dest or storage在哪里存储文件
fileFilter文件过滤器,控制哪些文件可以被接受
limits限制上传的数据
preservePath保存包含文件名的完整文件路径
通常,一般的网页应用,只需要设置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属性。

none()

只接受文本域。如果任何文件上传到这个模式,将发生 "LIMIT_UNEXPECTED_FILE" 错误。这和upload.fields([])的效果一样。

any()

接受一切上传的文件。文件数组将保存在req.files。

警告: 确保你总是处理了用户的文件上传。永远不要将 multer 作为全局中间件使用,因为恶意用户可以上传文件到一个你没有预料到的路由,应该只在你需要处理上传文件的路由上使用。

如何存放磁盘?

磁盘存储引擎 (DiskStorage)

磁盘存储引擎可以让你控制文件的存储。

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, '/tmp/my-uploads')
  },
  filename: function (req, file, cb) {
    cb(null, file.fieldname + '-' + Date.now())
  }
})

const upload = multer({ storage: storage })

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

destination是用来确定上传的文件应该存储在哪个文件夹中。也可以提供一个string(例如'/tmp/uploads')。如果没有设置destination,则使用操作系统默认的临时文件夹。

注意: 如果你提供的destination是一个函数,你需要负责创建文件夹。当提供一个字符串,Multer将确保这个文件夹是你创建的。filename用于确定文件夹中的文件名的确定。 如果没有设置filename,每个文件将设置为一个随机文件名,并且是没有扩展名的。

注意: Multer不会为你添加任何扩展名,你的程序应该返回一个完整的文件名。每个函数都传递了请求对象 (req) 和一些关于这个文件的信息 (file),有助于你的决定。注意: req.body可能还没有完全填充,这取决于向客户端发送字段和文件到服务器的顺序。

内存存储引擎 (MemoryStorage)

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

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

当使用内存存储引擎,文件信息将包含一个buffer字段,里面包含了整个文件数据。

警告: 当你使用内存存储,上传非常大的文件,或者非常多的小文件,会导致你的应用程序内存溢出。

limits 大小限制

一个对象,指定一些数据大小的限制。Multer 通过这个对象使用 busboy。

可以使用下面这些:

KeyDescriptionDefault
fieldNameSizefield 名字最大长度100 bytes
fieldSizefield 值的最大长度1MB
fields非文件 field 的最大数量无限
fileSize在 multipart 表单中,文件最大长度 (字节单位)无限
files在 multipart 表单中,文件最大数量无限
parts在 multipart 表单中,part 传输的最大数量(fields + files)无限
headerPairs在 multipart 表单中,键值对最大组数2000

设置 limits 可以帮助保护你的站点抵御拒绝服务 (DoS) 攻击。

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的所有相关介绍以及使用方法,为了大家更好的理解以及使用Multer,下面给大家再分享一下我个人博客写的一个上传接口,以便大家更容易的使用它。这个接口本身是使用typescript写的,为了让大家更容易看明白,我为大家已经简化成普通js了,以下是相关代码。

Demo

import express from 'express';
import fs from 'fs';
import multer from 'multer';
import path from 'path';

let app = express(),
coverPath = path.resolve(__dirname, '../../assets/images/cover'),
//创建dir
createFolder = folder => {
  try {
    fs.accessSync(folder);
   } catch (e) {
    fs.mkdirSync(folder);
   }
},
//设置文件后缀 & 存储路径
storage = path => multer.diskStorage({
   //存储文件路径
   destination: (req, file, cb) => {
      cb(null, path);
   },
   //文件名称,默认不带后缀,补上后缀
   filename: (req, file, cb) => {
      let originalname = file.originalname;
      cb(null, utils.MD5(Date.now().toString()) + '_' + originalname);
   }
}),
//接口响应
release = ( req, res, err) => {
   if (err || !req.file) {
      return res.json({
        success: false,
        errorCode: '',
        errorMsg: '文件上传失败',
        data: err
      });
    }

    res.json({
        success: true,
        errorCode: '',
        errorMsg: '文件上传成功',
        data: {
            imgUrl: `//static.wujiabk.com/images/cover/${req.file.filename}` || ''
        }
    });
}

createFolder(coverPath) //保证存储目录的存在性,先创建目录
const uploadCover = multer({ storage: storage(coverPath) }).single('file')
app.post('/upload/cover', uploadCover, (req, res, next) => {
  uploadCover(release);
});

点击查看所有示例集合

转载请务必注明出处,欢迎分享

前端资料库 2019-01-24 19:53:23 通过 网页 浏览(1014)

共有0条评论!

发表评论