Nest 的文件上传是基于 Express 的中间件 multer 实现的,在学习 Nest 文件上传之前,先学习下 multer 包的使用
新建一个文件夹
cors 包是处理跨域 header
index.js
const express = require('express')
const multer = require('multer')
const cors = require('cors');
const app = express()
app.use(cors());
const upload = multer({ dest: 'uploads/' })
app.post('/aaa', upload.single('aaa'), function (req, res, next) {
console.log('req.file', req.file);
console.log('req.body', req.body);
})
app.listen(3000);
新建 index.html
通过 FormData + axios 上传文件,指定内容的传输格式 content-type 为 multipart/form-data。
(axios 会自动根据内容指定 content-type,不需要手动指定)
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script>
</head>
<body>
<input id="fileInput" type="file" />
<script>
const fileInput = document.querySelector("#fileInput");
async function formData() {
const data = new FormData();
data.set("name", "fuhao");
data.set("age", 18);
data.set("aaa", fileInput.files[0]);
const res = await axios.post("http://localhost:3000/aaa", data);
console.log(res);
}
fileInput.onchange = formData;
</script>
</body>
</html>
用 node 把 server 跑起来,并且用 http-server 把静态服务跑起来
上传文件
这就是 form-data 的传输格式
服务端看下
req.file 拿到文件字段,非文件字段在 req.body
服务端多了 uploads 目录,下面保存着上传文件
这是单文件 上传 那多文件上传呢?
index.js 添加 /bbb
const express = require('express')
const multer = require('multer')
const cors = require('cors');
const app = express()
app.use(cors());
const upload = multer({ dest: 'uploads/' })
app.post('/aaa', upload.single('aaa'), function (req, res, next) {
console.log('req.file', req.file);
console.log('req.body', req.body);
})
app.post('/bbb', upload.array('bbb', 2), function (req, res, next) {
console.log('req.files', req.files);
console.log('req.body', req.body);
})
app.listen(3000);
index.html 支持多文件
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script>
</head>
<body>
<input id="fileInput" type="file" multiple />
<script>
const fileInput = document.querySelector("#fileInput");
async function formData2() {
const data = new FormData();
data.set("name", "fuhao");
data.set("age", 20);
[...fileInput.files].forEach((item) => {
data.append("bbb", item);
});
const res = await axios.post("http://localhost:3000/bbb", data);
console.log(res);
}
fileInput.onchange = formData2;
</script>
</body>
</html>
如果超过 2个文件 就会默认报错
改一下这个 错误
app.post('/bbb', upload.array('bbb', 2), function (req, res, next) {
console.log('req.files', req.files);
console.log('req.body', req.body);
}, function(err, req, res, next) {
if(err instanceof multer.MulterError && err.code === 'LIMIT_UNEXPECTED_FILE') {
res.status(400).end('Too many files uploaded');
}
})
更复杂一点的情况,如果多个字段都会上传文件,而且限制也都不同呢?
index.js 更新
app.post('/ccc', upload.fields([
{ name: 'aaa', maxCount: 3 },
{ name: 'bbb', maxCount: 2 }
]), function (req, res, next) {
console.log('req.files', req.files);
console.log('req.body', req.body);
})
index.html 更新
async function formData3() {
const data = new FormData();
data.set("name", "fuhao");
data.set("age", 20);
data.append("aaa", fileInput.files[0]);
data.append("aaa", fileInput.files[1]);
data.append("bbb", fileInput.files[2]);
data.append("bbb", fileInput.files[3]);
const res = await axios.post("http://localhost:3000/ccc", data);
console.log(res);
}
fileInput.onchange = formData3;
如何修改保存的文件名?
const express = require('express')
const multer = require('multer')
const cors = require('cors');
const path = require('path')
const app = express()
app.use(cors());
const storage = multer.diskStorage({
destination(req, file, cb) {
cb(null, 'uploads/')
},
filename(req, file, cb) {
// 原始文件名
const ext = path.extname(file.originalname)
const name = path.basename(file.originalname, ext)
// 自定义规则
const newName = `${name}-${Date.now()}${ext}`
cb(null, newName)
}
})
const upload = multer({ storage })
app.post('/aaa', upload.single('aaa'), function (req, res, next) {
console.log('req.file', req.file);
console.log('req.body', req.body);
})
app.post('/bbb', upload.array('bbb', 2), function (req, res, next) {
console.log('req.files', req.files);
console.log('req.body', req.body);
}, function(err, req, res, next) {
if(err instanceof multer.MulterError && err.code === 'LIMIT_UNEXPECTED_FILE') {
res.status(400).end('Too many files uploaded');
}
})
app.post('/ccc', upload.fields([
{ name: 'aaa', maxCount: 3 },
{ name: 'bbb', maxCount: 2 }
]), function (req, res, next) {
console.log('req.files', req.files);
console.log('req.body', req.body);
})
app.listen(3000);