文件上传
原生表单
前端
原生表单需要设置 3 个属性:
action
属性,即提交地址;method
属性指定表单提交请求类型;get
post
put
delete
- ...
enctype
属性指定表单提交内容类型;application/x-www-form-urlencoded
:默认值multipart/form-data
:适用于使用<input>
标签上传文件text/plain
:文本类型
原生表单如果想要上传多个文件,需要多个<input>
标签,且name
属性唯一;否则使用自定义 formData的上传方式。
<form action="/submit" method="post" enctype="multipart/form-data">
<label for="file">file:</label>
<input type="file" id="file" name="file">
<input type="submit" value="提交"></input>
</form>
后端
fileUpload
:处理文件的中间件;
const express = require('express');
const path = require('path');
const fileUpload = require('express-fileupload');
const app = express();
app.use(fileUpload());
app.post('/submit', (req, res) => {
for (const key in req.files) {
req.files[key].mv(path.resolve(__dirname, 'upload', req.files[key].name));
}
res.send('ok');
});
app.listen('8080');
自定义 formData
前端
FormData
:接口提供了一种表示表单数据的键值对 key/value 的构造方式;- 当请求头
Content-type
为multipart/form-data
时,它会使用和表单一样的格式; - 该数据是可以被
for...of
遍历的;
- 当请求头
注意此时不要显示将Content-type
置为multipart/form-data
,手动添加会缺少boundary
属性,导致后端无法正常解析。
<label for="file"></label>
<input type="file" id="file" multiple onchange="handleFiles(this.files)" />
<button onclick="submit()">提交</button>
const formData = new FormData();
function handleFiles(files) {
for (const file of files) {
formData.set(file.name, file);
}
}
function submit() {
fetch('/submit', { body: formData, method: 'post' });
}
后端
与原生表单接收服务器一样
const express = require('express');
const path = require('path');
const fileUpload = require('express-fileupload');
const app = express();
app.use(fileUpload());
app.post('/submit', (req, res) => {
for (const key in req.files) {
req.files[key].mv(path.resolve(__dirname, 'upload', req.files[key].name));
}
res.send('ok');
});
app.listen('8080');
base64
前端
FileReader
:可以读取File
或Blob
对象中的文件数据(注:File
继承了Blob
);readAsDataURL
方法:读取Blob
数据转为base64
,存保存在result
属性中;onload
事件:读取完成时触发;result
属性:保存readAsDataURL
方法读取的数据(数据格式:由文件类型 + base64 标识 + base64 数据 构成)
一个 ASCII 字符需要 8bit 来表示,一个 base64 字符需要 6bit 来表示;6 个 ASCII 字符就需要 8 个 base64 字符表示。在数据传输上来说是增加体积,所以一般不用 base64 来传较大体积的数据。
<label for="file"></label>
<input type="file" id="file" onchange="handleFiles(this.files)" />
<button onclick="submit()">提交</button>
const uploadData = [];
function handleFiles(files) {
for (const file of files) {
const fr = new FileReader();
fr.onload = function () {
uploadData.push({ name: file.name, data: this.result.split(';base64,')[1] });
};
fr.readAsDataURL(file);
}
}
function submit() {
fetch('/submitbase64', {
body: JSON.stringify(uploadData),
method: 'post',
headers: {
'Content-Type': 'application/json'
}
});
}
后端
const express = require('express');
const path = require('path');
const fs = require('fs');
const app = express();
app.use(express.json());
app.post('/submitbase64', (req, res) => {
for (const data of req.body) {
fs.writeFileSync(path.resolve(__dirname, 'upload', data.name), data.data, 'base64');
}
res.sendStatus(200);
});
app.listen('8080');
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通