nodejs之接收formdata表单
1.3k5WEBnodejs2018-10-09

最近在学习express,写一个vue+express+mysql的小demo,需要上传一张封面图和一些其他的表单字段….

背景介绍

formdata主要用于发送表单数据,将数据编译成键值对的形式使用XMLHttpRequest来发送,一般的请求通常使用序列化的方法发送formdata格式的数据,所以formdata对象比较常见的应用场景是发送文件或者通过HTML表单创建的formdata对象用以发送表单
** 那么使用express搭建的nodejs的后台如何获取前台发送的formdata格式的数据 **

Multer中间件

Multer 是一个 node.js 中间件,用于处理 multipart/form-data 类型的表单数据

首先安装并存储在packjson中

1
npm install --save multer

配置

Multer 需要接受一个 options 对象,用于对文件上传时做一些控制,比如文件存储,大小限制等
所以在路由文件中除了引入 multer 模块还要设置 options 对象

  • dest or storage: 在哪里存储文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // 一般情况下只要设置 dest 属性设置文件存储的位置
    var multer = require('multer')
    var upload = multer({ dest: 'uploads/' })

    "但如果你想要设置更多,那么需要使用storage代替dest"

    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 })
  • fileFilter: 文件过滤器,控制哪些文件可以被接受,接收一个函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function fileFilter (req, file, cb) {
    // 你可以通过判断file的参数来判断这个文件是否跳过或者上传以及报错
    // 拒绝这个文件
    cb(null, false)
    // 接受这个文件
    cb(null, true)
    // 发送一个错误:
    cb(new Error('I don\'t have a clue!'))
    }
  • limits: 限制上传的数据,接受一个对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    {
    "fieldNameSize" // field 名字最大长度 100 bytes
    "fieldSize" // field 值的最大长度 1MB
    "fields" // 非文件 field 的最大数量 无限
    "fileSize" // 在 multipart 表单中,文件最大长度 (字节单位) 无限
    "files" // 在 multipart 表单中,文件最大数量 无限
    "parts" // 在 multipart 表单中,part 传输的最大数量(fields + files) 无限
    "headerPairs" // 在 multipart 表单中,键值对最大组数 2000
    }

方法

  • .single(fieldname)接受一个参数名为fieldname的文件
    应用场景:单个文件上传 + 一些其他的表单字段

    1
    2
    3
    4
    app.post('/profile', upload.single('avatar'), function (req, res, next) {
    // req.file 是 `avatar` 文件的信息
    // req.body 将具有文本域数据,如果存在的话
    })
  • .array(fieldname, maxCount) 接受一个参数名为fieldname的文件数组, 可选参数maxcount限制上传的最大数量
    应用场景:适合参数名相同的多文件上传 + 一些其他的表单字段

    1
    2
    3
    4
    app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
    // req.files 是 `photos` 文件数组的信息
    // req.body 将具有文本域数据,如果存在的话
    })
  • .fields(fields) 接受一个对象数组[{name:"",maxCount: 1},],每个对象应该具有 name 和可选的 maxCount 属性,
    应用场景:适合参数名不同的多文件上传 + 一些其他的表单字段

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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) 键是文件名,值是文件数组
    //
    // 例如:
    // req.files['avatar'][0] -> File
    // req.files['gallery'] -> Array
    //
    // req.body 将具有文本域数据,如果存在的话
    })
  • .none() 只接受文本域

  • .any() 接受一切。文件数组将保存在 req.files。

代码参考

在demo中的应用场景,很简单的单张图片上传+其他表单字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const express = require("express");
const router = express.Router();
var multer = require("multer");

let storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, "img");
},
filename: function(req, file, cb) {
// Multer 不会为你添加任何扩展名,所以完整的名字需要我们自己拼接
cb(null, Date.now() + "." + file.originalname.split(".")[1]);
}
});

let limits = {
files: 1, // 只接收一个文件
fileSize: 2097152 // 文件大小不超过2m
};

function fileFilter(req, file, cb) { // 文件类型判断
file.mimetype.split("/")[0] === "image" ? cb(null, true) : cb(null, false);
}

let upload = multer({
storage: storage,
fileFilter: fileFilter,
limits: limits
});

router.post("/insert", upload.single("img"), (req, res, next) => {
if (err) throw err;
else {
res.json(req.body);
}
});

req.file获取到的参数

1
2
3
4
5
6
7
8
fieldname: 'img',  // 表单字段名称
originalname: '1.png', // 上传时在用户电脑上的名称
encoding: '7bit', // 文件编码
mimetype: 'image/png', // 文件类型
destination: '/', // 接受后的保存路径
filename: 'img-1539066538986', // 保存在 destination 中的文件名
path: '\\img-1539066538986', // 已上传文件的完整路径
size: 80419 // size

参考文章

express文档 http://www.expressjs.com.cn/4x/api.html#req.body
multer文档 https://github.com/expressjs/multer/blob/master/README.md