加载中...

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

吴佳
2019-06-28 14:07:04
分类:NodeJs
6435
4
0

什么是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

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

Multer(opts) 参数

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

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

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

Key Description
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。

可以使用下面这些:

Key Description Default
fieldNameSize field 名字最大长度 100 bytes
fieldSize field 值的最大长度 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);
});

扫码关注后,回复“资源”免费领取全套视频教程

前端技术专栏

4

发表评论(共0条评论)

请输入评论内容
啊哦,暂无评论数据~