JavaScript 文件上传
上传类型
在 JavaScript 中,图片和文件上传到后台时,核心数据类型是 FormData(表单数据对象),
它用于模拟传统 HTML 表单的 multipart/form-data 编码格式 —— 这是文件上传的标准格式,能同时携带文件二进制数据和普通文本参数(如文件名、用户 ID 等)。
前端上传文件的过程
- 前端文件如何存储的?
- 浏览器中,文件的原始数据存储在 File 对象中(File 是 Blob 的子类,Blob 代表二进制大对象,File 在此基础上增加了文件名、修改时间等元信息)。
- 直接向后台发送 file 流吗?
- 注意 File 无法直接发送给后台,必须通过 FormData 封装后,再通过 XMLHttpRequest 或 Fetch API 发送。
- 那么前端如何封装呢?
html
<!-- HTML 获取 file 对象 -->
<input type="file" id="fileInput" accept="image/*">
<script>
// JS:获取File对象
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', (e) => {
const selectedFile = e.target.files[0]; // 选中的第一个文件(File对象)
if (selectedFile) {
console.log('文件类型:', selectedFile.type); // 如 "image/png"
console.log('文件大小:', selectedFile.size); // 如 204800(200KB)
uploadFile(selectedFile); // 调用上传函数
}
});
</script>js
/* JS 将 file 对象转化为 formData 对象,然后通过 ajax 请求将 formData 对象以 post 请求的 body 体的方式发送给服务端口 */
function uploadFile(file) {
// 1. 创建FormData对象
const formData = new FormData();
// 2. 向FormData中添加文件(key为"file",与后台接收参数名对应)
formData.append('file', file);
// 3. 可额外添加普通文本参数(如用户ID、文件描述)
formData.append('userId', '123');
formData.append('fileDesc', '个人头像');
// 4. 用Fetch API发送请求(无需手动设置Content-Type,浏览器会自动处理)
fetch('/api/upload', {
method: 'POST',
body: formData, // 核心:将FormData作为请求体
})
.then(response => response.json())
.then(data => console.log('上传成功:', data))
.catch(error => console.error('上传失败:', error));
}- 后端如何解析呢?以 express.js 为例
- 需要借助中间件 multer 解析 multipart/form-data,req.file 对应单个文件。多数框架需手动引入中间件,如 Express 的 multer、Flask 的 flask-uploads
拓展
除了 FormData,有时会将图片转为 Base64 字符串上传(本质是将二进制数据编码为文本),此时前端发送的是普通文本参数,后台接收后需解码为二进制再处理。 Base64 编码会使文件体积增大 30% 左右,传输效率低,不适合大文件(如视频、压缩包),所以其不适合大文件
js
// 1. 将图片File转为Base64字符串
function fileToBase64(file) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = (e) => resolve(e.target.result); // 结果为Base64字符串(如 "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...")
reader.readAsDataURL(file);
});
}
// 2. 上传Base64字符串(请求体为JSON,Content-Type: application/json)
async function uploadBase64File(file) {
const base64Str = await fileToBase64(file);
fetch('/api/upload-base64', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
fileBase64: base64Str,
fileName: file.name,
userId: '123'
})
});
}总结
FormData 和 Base64两种方式对比
shell
上传方式 前端核心类型 后台接收格式 适用场景
FormData(推荐) FormData multipart/form-data 所有文件类型(图片、视频、文档等),尤其是大文件
Base64(备选) 字符串 application/json 小图片(如头像、图标),适配老旧接口