使用原生进行文件上传
from的方式
<!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>
enctype=”multipart/form-data” 这个编码方式是啥 为神马要这样呢? 对请求头有何影响
上传成功后的请求头
使用es6的fetchAPI上传图片
<!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>
enctype=”multipart/form-data” 这个编码方式是啥 对请求头有何影响
当使用postman发送上传图片的请求的code
你会发现——WebKitFormBoundary7MA4YWxkTrZu0gW这个动出现三次 这又是啥
先从
Content-Type
enctype=”multipart/form-data”
enctype是编码格式
multipart/form-data 是一种传输文件的格式如下图
boundary=——WebKitFormBoundary7MA4YWxkTrZu0gW
从这个图你就能看出来,最开始是以boundary=——WebKitFormBoundary7MA4YWxkTrZu0gW 开始的,而后面的数据也是
这不就是明显的分割符吗,而boundary的中文意思就是分割符,你再看图片,头部一次尾部一次,剩余的每个数据用这个分分割一次,
而boundary后面的字符知识随机生成出来的分割字符,这种格式很适合传输大数据。
上传的原理
上传不就是将文件读成二进制数据后编码发送给后端吗。说白就是body中的一段数据,其实get请求也能上传文件,实际上数据是发送过去的,只是服务器不认而已
express中实现文文件上传
需要使用的组件:multer
文档:https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md
剩余的自己看文档
示例:
const express = require('express');
const path = require('path');
const multer = require('multer'); // 上传文件的中间件
// 路由
const router = express.Router();
// 默认格式
// const upload = multer({
// dest: path.resolve(__dirname, '../public/img')
// })
const storage = multer.diskStorage({
// 储存位置
destination: function (req, file, cb) {
cb(null, path.resolve(__dirname, '../public/img'));
},
// 文件名 默认是没有后缀名的
filename: function (req, file, cb) {
const ext = path.extname(file.originalname);
const timeStamp = Date.now();
const randomStr = Math.random().toString(36).slice(-6);
const filename = `${timeStamp}${randomStr}${ext}`;
cb(null, filename);
},
});
const upload = multer({
storage, // 磁盘存储引擎
// 限制数据得大小
limits: {
fileSize: 1024 * 1024 * 3,
},
// 那些文件可以上传
fileFilter: (req, file, cb) => {
cb(null, true);
const extname = file.originalname;
const whitelist = ['.jpg', '.png', '.gif'];
let istrue = false;
whitelist.forEach((ele) => {
if (extname.includes(ele)) {
cb(null, true);
istrue = true;
} else {
cb(null, false);
}
});
if (!istrue) {
cb(new Error(`your ext name of ${extname} is not support`));
}
},
});
// 单个数据
router.post('/', upload.single('img'), (req, res) => {
const url = `/upload/${req.file.filename}`;
res.send({
code: 0,
msg: '',
data: url,
});
});
module.exports = router;
express.js
const express = require('express');
const app = express();
app.use('/api/upload', require('./upload'))