Skip to content

JavaScript 文件上传

上传类型

在 JavaScript 中,图片和文件上传到后台时,核心数据类型是 FormData(表单数据对象),

它用于模拟传统 HTML 表单的 multipart/form-data 编码格式 —— 这是文件上传的标准格式,能同时携带文件二进制数据和普通文本参数(如文件名、用户 ID 等)。

前端上传文件的过程

  1. 前端文件如何存储的?
    • 浏览器中,文件的原始数据存储在 File 对象中(File 是 Blob 的子类,Blob 代表二进制大对象,File 在此基础上增加了文件名、修改时间等元信息)。
  2. 直接向后台发送 file 流吗?
    • 注意 File 无法直接发送给后台,必须通过 FormData 封装后,再通过 XMLHttpRequest 或 Fetch API 发送。
  3. 那么前端如何封装呢?
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));
}
  1. 后端如何解析呢?以 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       小图片(如头像、图标),适配老旧接口