Express结合中间件Multer保存上传文件或文件夹
multer
是 express
官方推荐的文件上传中间件,它是在 busboy
的基础上开发的。目前 multer
的最新版本为:~1.1.0。本文所有代码段均使用此版本。
# 安装 multer 中间件
npm i multer --save
1
# 封装 multer 中间件
let multer=require('multer');
let storage = multer.diskStorage({
//设置上传后文件路径,uploads文件夹会自动创建。
destination: function (req, file, cb) {
cb(null, './public/uploads')
},
//给上传文件重命名,获取添加后缀名
filename: function (req, file, cb) {
let fileFormat = (file.originalname).split(".");
cb(null, file.fieldname + '-' + Date.now() + "." + fileFormat[fileFormat.length - 1]);
}
});
//添加配置文件到muler对象。
let upload = multer({
storage: storage
});
//如需其他设置,请参考multer的limits,使用方法如下。
//let upload = multer({
// storage: storage,
// limits:{}
// });
//导出对象
module.exports = upload;
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 使用 multer 中间件
const express = require('express');
const fs = require('fs');
const path = require('path');
const router = express.Router();
const muilter = require('./multerUtil');
//multer有single()中的名称必须是表单上传字段的name名称。
const upload = muilter.single('file');
// 上传文件
router.post('/add', upload, (req, res, next) => {
if (err) {
return console.log(err);
}
//文件信息在req.file或者req.files中显示。
console.log(req);
});
module.exports = router;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 错误处理机制
当遇到一个错误,multer
将会把错误发送给 express
。你可以使用一个比较好的错误展示页 (express
标准方式)。
如果你想捕捉 multer
发出的错误,你可以自己调用中间件程序。如果你想捕捉 Multe
错误,你可以使用 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) {
// 发生错误
}
// 一切都好
})
})
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 使用案例
前端通过 axios 将文件信息传送到服务端
handleAddFile() {
this.file=[{
lastModified: 1618279848617,
lastModifiedDate: Tue Apr 13 2021 10:10:48 GMT+0800 (中国标准时间) {},
name: "chunk-ee64b042.517eefa7.css",
size: 7656,
state: true,
type: "text/css",
webkitRelativePath: "dist/css/chunk-ee64b042.517eefa7.css"
}]
this.file.forEach((item, i) => {
let formData = new FormData();
formData.append("file", item, item.name);
this.$axios.post("/swd/fileEdit/add", formData, {
headers: {
"www-name": this.www, //上传的文件根目录名称
webkitRelativePath: item.webkitRelativePath, //文件路径名
},
})
.then((res) => {
if (res.data.code === 200) {
console.log("文件上传成功!");
}
});
});
}
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
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
服务端接收前端传过来的文件信息
const express = require('express');
const fs = require('fs');
const path = require('path');
const router = express.Router();
const multer = require('multer');
const writeFileRecursive = function (path, buffer, callback) {
let lastPath = path.substring(0, path.lastIndexOf("/"));
fs.mkdir(lastPath, { recursive: true }, (err) => {
if (err) return callback(err);
fs.writeFile(path, buffer, function (err) {
if (err) return callback(err);
return callback(null);
});
});
}
router.post('/add', multer().single('file'), (req, res, next) => {
let wwwName = req.get('www-name'); //文件存储的目录名称
let relativePath = req.get('webkitRelativePath'); //文件或文件夹路径
relativePath = relativePath ? './www/' + wwwName + '/' + relativePath.slice(relativePath.indexOf('/'), relativePath.length) : './www/' + wwwName + '/' + req.file.originalname
/****** 方法一:直接写入 ******/
let fileData = req.file.buffer.toString();
writeFileRecursive(relativePath, fileData, (err) => {
if (err) {
res.json({ code: 500, message: req.file.originalname + "文件写入失败!" });
console.error(err)
} else {
res.json({ code: 200, message: req.file.originalname + "文件写入成功!" });
console.log(req.file.originalname + "文件写入成功!")
};
});
/****** 方法二:使用流写入 ******/
body.filePath = path.join(__dirname, `../${basePath}/${body.path}`);
// let p2 = fse.write(body.filePath, files)
let fileStream = fse.createWriteStream(body.filePath);
fileStream.write(req.file.buffer);
fileStream.end()
fileStream.on('error', function (err) {
//console.log("error",err);
});
fileStream.on('finish', function (res) {
console.log("finish");
});
});
module.exports = router;
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
36
37
38
39
40
41
42
43
44
45
46
47
48
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
36
37
38
39
40
41
42
43
44
45
46
47
48
# 其他示例
// 接收ico的图片
let icoPath = path.join(__dirname, `../../assets/navicon`)
fs.ensureDirSync(icoPath)
let multerIcon = multer({
storage: multer.diskStorage({
destination: function (req, file, cb) {
cb(null, icoPath);
},
filename: function (req, file, cb) {
let changedName = (new Date().getTime()) + '-' + file.originalname;
cb(null, changedName);
}
})
});
router.post('/icon', multerIcon.single('file'), (req, res, next) => {
res.json({
code: 200,
url: "/navicon/" + req.file.filename,
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 相关资料
multer的官方地址:https://github.com/expressjs/multer (opens new window)
上次更新: 2024/01/30, 00:35:17
- 02
- Node与GLIBC_2.27不兼容解决方案08-19
- 03
- Git清空本地文件跟踪缓存08-13