当前位置: 首页 > news >正文

10.4FormData :前端文件上传与表单数据处理的核心工具

什么是 FormData

FormData 是一个 JavaScript 对象,用于表示 HTML 表单数据。它可以模拟表单控件的键值对,并支持 字符串二进制数据(如文件) 的混合提交。

✅ 主要用途:

  • 文件上传(图片、视频、文档等)
  • 提交包含文件的复杂表单
  • 构造 multipart/form-data 请求体
  • 与 fetchXMLHttpRequestaxios 配合使用

创建 FormData 实例

1. 空的 FormData

const formData = new FormData();

2. 从现有 <form> 元素创建

<form id="myForm"><input name="username" value="Alice" /><input type="file" name="avatar" />
</form>
const form = document.getElementById('myForm');
const formData = new FormData(form);
// 自动包含所有表单字段

 三、添加数据:append(key, value, filename?)

语法:

formData.append(key, value, filename);
参数说明
key字段名(字符串)
value值,可以是字符串、BlobFile
filename可选,上传时的文件名(仅当 value 是 Blob/File 时有效)

示例:

const formData = new FormData();// 添加字符串
formData.append('username', 'Alice');
formData.append('email', 'alice@example.com');// 添加文件(来自 input)
const fileInput = document.querySelector('input[type=file]');
const file = fileInput.files[0];
formData.append('avatar', file, 'my-avatar.jpg'); // 指定文件名// 添加 Blob(如 canvas 截图)
canvas.toBlob(blob => {formData.append('screenshot', blob, 'screen.png');
});// 添加多文件(同名)
formData.append('photos', file1);
formData.append('photos', file2);

读取数据的方法

由于 FormData 不是普通对象,不能用 formData.key 取值。

1. formData.get(key) —— 获取第一个匹配的值

适用于单值字段(如 name、email 等)

const formData = new FormData();
formData.append('username', 'Alice');
formData.append('avatar', file); // file 是 File 对象console.log(formData.get('username')); // "Alice"
console.log(formData.get('avatar'));   // File 对象

⚠️ 注意:如果同一个 key 有多个值,get() 只返回第一个


2. formData.getAll(key) —— 获取某个 key 的所有值

适用于多文件上传或复选框等场景

formData.append('photos', file1);
formData.append('photos', file2);console.log(formData.getAll('photos')); 
// [File, File]

3. formData.has(key) —— 判断是否包含某个 key
if (formData.has('username')) {console.log('包含用户名');
}

4. 遍历所有数据:使用 formData.entries()(推荐)
for (let [key, value] of formData.entries()) {console.log(key, value);// 示例输出:// username  "Alice"// avatar    File { name: "avatar.jpg", ... }
}// 遍历所有键值对
for (let [key, value] of formData.entries()) {console.log(key, value);
}// 只遍历键
for (let key of formData.keys()) {console.log(key);
}// 只遍历值
for (let value of formData.values()) {console.log(value);
}

✅ 这是最常用的方式,适合调试或序列化所有数据。


5. 转成普通对象(仅限字符串值,不推荐用于文件
function formDataToObject(formData) {const obj = {};for (let [key, value] of formData.entries()) {// 注意:如果是 File 对象,这里会变成 [object File]obj[key] = value;}return obj;
}const obj = formDataToObject(formData);
console.log(obj); // { username: "Alice", avatar: File }

⚠️ 注意:如果值是 FileBlob,转成对象后无法还原为原始文件内容,仅用于查看结构

修改与删除

1. set(key, value, filename?) —— 设置值(会覆盖已有)

formData.set('username', 'Bob'); // 替换所有 username 的值

⚠️ 注意:set() 会删除所有同名字段,再添加新值。

2. delete(key) —— 删除某个字段的所有值

formData.delete('tempImage');

发送请求(与 fetch / axios 配合)

✅ 使用 fetch

//原生 fetch 不支持上传进度事件(不像 axios 的 onUploadProgress)<input type="text" id="username" value="Alice" />
<input type="file" id="avatar" />
<button onclick="upload()">上传</button>async function upload() {const username = document.getElementById('username').value;const fileInput = document.getElementById('avatar');const file = fileInput.files[0];if (!file) {alert('请先选择文件');return;}// 创建 FormDataconst formData = new FormData();formData.append('username', username);formData.append('avatar', file); // 字段名需与后端一致try {const response = await fetch('/api/upload', {method: 'POST',body: formData// ⚠️ 不要设置 Content-Type!});if (!response.ok) {throw new Error(`HTTP ${response.status}: ${response.statusText}`);}const result = await response.json();console.log('上传成功:', result);} catch (error) {console.error('上传失败:', error);}
}

✅ 使用 axios

<input type="file" id="avatar" />
<input type="text" id="username" value="Alice" />
<button onclick="upload()">上传</button>async function upload() {const fileInput = document.getElementById('avatar');const usernameInput = document.getElementById('username');const file = fileInput.files[0];const username = usernameInput.value;if (!file) {alert('请选择文件');return;}// 创建 FormDataconst formData = new FormData();formData.append('username', username);formData.append('avatar', file); // 字段名需与后端一致try {const response = await axios.post('/api/upload', formData, {// ⚠️ 注意:不要设置 Content-Type// headers: {//   'Content-Type': 'multipart/form-data'  // ❌ 错误!会破坏 boundary// },onUploadProgress: (progressEvent) => {const percent = (progressEvent.loaded / progressEvent.total) * 100;console.log(`上传进度: ${percent.toFixed(2)}%`);}});console.log('上传成功:', response.data);} catch (error) {console.error('上传失败:', error.response?.data || error.message);}
}

🔔 重要:不要手动设置 Content-Type


📂 七、文件处理技巧

1. 从网络图片创建 File 并添加

async function addImageFromURL(url) {const response = await fetch(url);const blob = await response.blob();const file = new File([blob], 'online.jpg', { type: blob.type });formData.append('image', file);
}

2. 限制文件类型/大小

const file = fileInput.files[0];
if (file.size > 2 * 1024 * 1024) {alert('文件不能超过 2MB');return;
}
if (!['image/jpeg', 'image/png'].includes(file.type)) {alert('只支持 JPG/PNG');return;
}
formData.append('photo', file);

常见注意事项

问题解决方案
手动设置 Content-Type❌ 不要设置,让浏览器自动设置
无法用 formData.key 取值✅ 使用 get() / getAll()
FormData 不是响应式(Vue)✅ 用普通数据管理,最后生成 FormData
跨域请求携带 cookie✅ fetch 加 credentials: 'include'axios 加 withCredentials: true
后端收不到文件✅ 检查字段名是否匹配,是否用了 multer 等中间件
http://www.dtcms.com/a/528874.html

相关文章:

  • 肇庆建网站在网站上显示备案信息
  • 如何批量获取蛋白质序列的所有结构域(domain)数据-1
  • 做兼职在线抠图网站本科自考科目有哪些
  • wordpress 下载模板站做的网站如何更换网站模板
  • Rust:Windows 系统 VsCode 环境搭建
  • 网站开发+接活创建一个网站的项目体现项目完成速度因素的
  • 双馈风力发电机控制系统仿真设计(论文+仿真)
  • 国内做性视频网站有哪些南京越城建设集团有限公司网站
  • Pytorch常用API(ML和DL)
  • 切水题2.0
  • 深入解析C++ String类的实现奥秘
  • 机器视觉的液晶电视OCA全贴合应用
  • 个人博客网站页面儿童玩具网站建设策划书
  • 构建大模型安全自动化测试框架:从手工POC到AI对抗AI的递归Fuzz实践
  • 数据库约束与查询:MySQL 中的 DQL 和约束全解析
  • C++笔记(面向对象)友元
  • 网站在工信部备案查询oa系统开发
  • FPGA基础知识(七):引脚约束深度解析--从物理连接到时序收敛的完整指南
  • Minecraft-Speed-Proxy——搭建专属的Minecraft加速IP
  • Flutter 异步 + 状态管理融合实践:Riverpod 与 Bloc 双方案解析
  • 10.25复习LRU缓存[特殊字符]
  • 做网站怎么那么难谷歌关键词排名查询工具
  • 门户网站的建设与维护注册域名多长时间
  • 实战:将 Nginx 日志实时解析并写入 MySQL,不再依赖 ELK
  • Redis 黑马点评day02 商户查询缓存
  • 品牌网站建设切入点wordpress很好的博客
  • ASP.NET Core读取Excel文件
  • 器材管理网站开发沈阳网站建设费用
  • 巧用 CSS linear-gradient 实现多种下划线文字特效(纯 CSS 无需额外标签)
  • 地州电视网站建设流程网址域名大全