multer
官网:https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md
由于单独封装上传文件的功能,需要做的事情比较繁琐这里直接使用multer库来操作
服务器
安装multer
npm i multer@1.4.2
创建路由器
由于图片作为静态资源(除非你想保存base64图片到数据库),所以不需要service层,只需要定义一个路由层就可以
const express = require('express');
const router = express.Router();
const multer = require('multer');
const path = require('path');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.resolve(__dirname, '../../public/upload'))
},
filename: function (req, file, cb) {
// 时间戳 - 6位随机字符.文件后缀
const timeStamp = Date.now();
const ramdomStr = Math.random().toString(36).slice(-6);
const ext = path.extname(file.originalname);
const filename = `${timeStamp}-${ramdomStr}${ext}`;
cb(null, filename);
}
})
const upload = multer({
storage,
limits: {
fileSize: 1024 * 2014 * 10
},
fileFilter(req, file, cb) {
// 文件名
const extname = path.extname(file.originalname);
const whiteList = ['.jpg', '.gif', '.png', '.jpeg'];
if (whiteList.includes(extname)) {
cb(null, true);
} else {
cb(new Error(`you ext name of ${extname} is not support`));
}
}
});
router.post('/', upload.single('avatar'), function (req, res, next) {
const url = `http://localhost:12306/upload/${req.file.filename}`;
res.send({
success: true,
uid: "0",
name: "IMG.png",
state: "done",
url: url,
downloadURL: url,
imgURL: url,
size: 2000
})
})
module.exports = router;
storage
,用来定义图片上传以后保存图片位置和文件名字的信息const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.resolve(__dirname, '../../public/upload'))
},
filename: function (req, file, cb) {
// 时间戳 - 6位随机字符.文件后缀
const timeStamp = Date.now();
const ramdomStr = Math.random().toString(36).slice(-6);
const ext = path.extname(file.originalname);
const filename = `${timeStamp}-${ramdomStr}${ext}`;
cb(null, filename);
}
})
destination
,定义上传图片的存放的位置- req: 请求头部的相关信息
- file: 上传的文件的相关信息
- cb: 回调函数,第一个参数表示没有错误产生,否则会直接报错,第二个参数存放文件的文件夹路径
filename
: 自定义存放文件的文件的名字- cb: 回调函数,第一个参数表示没有错误产生,否则会直接报错,第二个参数表示格式化后的文件名
upload
:对象const upload = multer({
storage,
limits: {
fileSize: 1024 * 2014 * 10
},
fileFilter(req, file, cb) {
// 文件名
const extname = path.extname(file.originalname);
const whiteList = ['.jpg', '.gif', '.png', '.jpeg'];
if (whiteList.includes(extname)) {
cb(null, true);
} else {
cb(new Error(`you ext name of ${extname} is not support`));
}
}
});
- multer返回一个对象,
- storage: 定义文件存放的路径和文件名
- limits: 文件大小,字节为单位
- fileFilter:过滤上传文件
- 参数: req,请求头,file,文件相关的信息,cb回调函数
- whiteList: 定义允许上传的文件类型
- 如果允许就直接回调会true
cb(null,true)
- 如果不允许,直接抛出错误给客户端
cb(new Error(
you ext name of ${extname} is not support));
第一个参数有值,会作为错误处理
创建路由
``json router.post('/', upload.single('avatar'), function (req, res, next) { const url =
http://localhost:12306/upload/${req.file.filename}`; res.send({success: true,
uid: "0",
name: "IMG.png",
state: "done",
url: url,
downloadURL: url,
imgURL: url,
size: 2000
}) })
- 返回的数据格式可以自定义
<a name="W3BL7"></a>
## 引用上传路由
```json
app.use('/api/upload', require('./api/upload'))
客户端
原生表单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<form action="/api/upload" method="POST" enctype="multipart/form-data">
<p>
<input type="text" name="a" />
</p>
<p>
<input type="file" name="img" />
</p>
<p>
<button>提交</button>
</p>
</form>
</body>
</html>
- entype :一定是要写成
multipart/form-data
,否则会有问题 - method: post
- 会直接把文件作为文件对象上传
ajax
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<p>
<input type="text" name="a" />
</p>
<p>
<input type="file" name="img" accept="image/*" multiple />
</p>
<p>
<button>提交</button>
</p>
<img src="" alt="" />
<script>
function upload() {
const inpA = document.querySelector("[name=a]");
const inpFile = document.querySelector("[name=img]");
const img = document.querySelector("img");
const formData = new FormData(); //帮助你构建form-data格式的消息体
formData.append("a", inpA.value);
for (const file of inpFile.files) {
formData.append("img", file, file.name);
}
fetch("/api/upload", {
body: formData,
method: "POST",
})
.then((resp) => resp.json())
.then((resp) => {
console.log(resp);
if (resp.code) {
//有错误
alert(resp.msg);
} else {
img.src = resp.data;
}
});
}
document.querySelector("button").onclick = upload;
</script>
</body>
</html>
- 需要借助
new FileReader()
来创建文件封装数据格式,否则数据发送到服务器会有问题