JavaScript如何正确将文件存入data对象并完成上传提交
问题根源
直接将File类型的文件对象挂载到普通JS对象属性上无法正常使用,核心原因是文件属于二进制资源,无法被普通对象结构直接承载做序列化传输:如果后续将普通对象转JSON发送给后端,序列化过程会自动丢弃File、Blob类型的属性值,自然无法拿到正确的文件内容。之前尝试FormData方案失败,基本都是字段嵌套写法错误、手动设置请求头等低级错误导致的。
正确实现方式
方案1:标准FormData上传(生产环境推荐,适配所有后端文件上传接口)
FormData是浏览器原生提供的、专门用于传输包含文件在内的表单数据的对象,注意它不支持直接传入嵌套结构,需要按字段层级拼接键名,代码示例:
// 先做判空校验,避免用户未选文件时报错 const fileNode = document.forms["form"]["file"]; if (!fileNode.files.length) { alert("请先选择要上传的身份证文件"); return; } const uploadFile = fileNode.files[0]; // 组装上传数据 const formData = new FormData(); // 普通数值字段直接追加 formData.append("input[amount]", 100); // 文件字段直接传入File对象即可 formData.append("input[identity_card]", uploadFile); // 接口请求注意:不要手动设置Content-Type请求头,浏览器会自动补全multipart/form-data对应的边界标识,手动设置反而会导致上传失败 // 以fetch请求为例 fetch("/your/upload/path", { method: "POST", body: formData })
方案2:前端逻辑暂存文件引用
如果不需要立刻上传,只是要在前端逻辑里暂存选中的文件引用,你原本的写法本身是可以拿到File对象的,失效基本是以下几个原因导致的,对应排查即可:
- 代码执行时机过早:DOM还未渲染完成、用户还没选中文件时就执行了赋值代码,此时
files[0]值为undefined - DOM选择器匹配失败:form标签的name属性不是
form,或者文件input的name属性不是file,导致拿不到对应的DOM节点 - 后续对数据做了JSON序列化:
JSON.stringify会自动过滤二进制类型属性,序列化后文件字段会直接丢失
正确的暂存写法建议绑定在文件选择框的change事件中,确保选完文件再取值:
document.forms["form"]["file"].addEventListener("change", function() { const data = { input: { amount: 100, identity_card: this.files[0] } } // 控制台打印能看到文件的name、size、type属性,就说明取值成功 console.log(data.input.identity_card); })
暂存的File对象不要做JSON序列化处理,后续需要上传时再组装到FormData中即可。
内容的提问来源于stack exchange,提问作者Therin ZINSOU
相关产品推荐
相关产品推荐

