前端文件上传功能
Request headers(请求头信息)
Request headers 是客户端向服务端发送http请求的一部分,它包含了Content-Type这个字段,指定了客户端发送的内容类型。
请求头可能有这些值:
- application/json:是JSON格式提交的方式,使用最广泛。
- application/x-www-form-urlencoded :这是form表单提交的时候的表示方式。
- multipart/form-data: 也是一个常见的POST数据提交的方式,一般是在使用表单上传文件时使用。
WARNING
当表单向服务器上传的内容包含文件时,使用multipart/form-data
html
<form action="" method="" id="formElem">
<div class="form-item">
<label for="name">name: </label>
<input type="text" name="name" value="John">
</div>
<div class="form-item">
<label for="avatar">avatar: </label>
<input
type="file"
name="avatar"
id="file"
accept="image/*"
required
/>
</div>
<div class="form-item">
<input type="submit" value="提交" />
</div>
</form>
使用XMLHttpRequest提交数据
js
const form = document.querySelector('#formElem')
form.onsubmit = async (e) => {
e.preventDefault();
const f = document.querySelector("#file").files;
const formObj = new FormData();
formObj.append("file", f[0]);
const xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:3000/file/upload", true);
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.onload = function () {
if (xhr.status == 200) {
alert("uploaded!");
}
};
xhr.send(f);
}
使用fetch提交数据
js
const form = document.querySelector('#formElem')
form.onsubmit = async (e) => {
e.preventDefault();
let response = await fetch('http://localhost:3000/file/upload', {
method: 'POST',
body: new FormData(form)
});
let result = await response.json();
alert(result.message);
};
服务端处理表单数据
服务端使用Node.js处理,引入Multer,官方明确指出它可以处理的数据形式为 multipart/form-data
TIP
Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files. It is written on top of busboy for maximum efficiency.
js
import * as multer from 'multer';
const storage = multer.diskStorage({
destination: function (req, file: any, cb) {
let des = './uploads';
if (file.mimetype.slice(0, 5) === 'image') des = './uploads/image';
if (file.mimetype.slice(0, 5) === 'audio') des = './uploads/audio';
if (file.mimetype.slice(0, 5) === 'video') des = './uploads/video';
cb(null, des);
},
filename: function (req, file: any, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9) + '.' + file.originalname.split('.').at(-1);
cb(null, uniqueSuffix);
},
});
它的disStorage接收的参数中可以获取到前端上传的file信息,可以根据这些信息进行文件分类,或者文件重新命名。
总结
有时候前端上传了文件但是服务端并没有解析到,可能是请求头Content-Type的问题。