使用form的target指向iframe是IE9及以下环境中唯一可靠的无刷新文件上传方式,需满足iframe有name且与target一致、已插入DOM且不嵌套在form内、style设为display:none三个条件。

直接用 form 的 target 指向 iframe 是目前唯一能在 IE9 及以下、老政务/金融专网等环境中可靠实现文件上传且不刷新页面的方式。它不是“真异步”,但能绕过 XMLHttpRequest 对 multipart/form-data 的兼容限制,且原生支持文件控件。
iframe 元素必须满足的三个硬性条件
缺一不可,否则表单会退化为整页跳转或静默失败:
-
iframe必须有name属性,且值与form的target属性**完全一致**(大小写敏感、不能有空格) -
iframe必须已插入 DOM,且不能套在form内部;推荐放在</body>前,与form同级 -
iframe必须设style="display:none"—— 用visibility:hidden或width="0" height="0"在旧版 IE 中会导致load事件不触发
form 标签和 enctype 的正确写法
关键不是加 JS 拦截,而是让原生提交行为“落”进 iframe:
-
form必须显式声明enctype="multipart/form-data",否则文件字段不会被编码发送 -
target值必须是字符串,不能是变量或表达式;例如target="upload-frame",对应<iframe name="upload-frame"></iframe> - 不要在
form.onsubmit里写return false或this.reset()—— 这会让请求根本发不出去
服务端响应必须返回可解析的 HTML
浏览器把响应当 HTML 加载进 iframe,不是 JSON 或纯文本:
立即学习“前端免费学习笔记(深入)”;
- Content-Type 必须是
text/html(不是application/json) - 响应体至少要包含
<html><body>...</body></html>结构,哪怕只有一行:<script>parent.handleResult({success:true})</script> - 如果返回纯 JSON 字符串(如
{"status":1}),必须包裹在<pre>标签里,否则iframe.contentDocument.body会是null - HTTP 状态码(如 500)不影响
load触发,错误状态必须靠响应体显式携带,不能依赖 status code 判断
读取响应和清空表单的唯一安全时机
所有操作必须等 iframe.onload 触发后进行,且需防御性检查:
- 绑定
onload必须在form提交前完成;动态创建的iframe要确保appendChild已执行 - 回调中先检查
iframe.contentWindow?.document?.body是否存在,再读textContent或执行script - 清空字段不能用
form.reset()—— 它会重置disabled和readonly状态;应遍历input/textarea/select,只清空可编辑字段:el.value = '' - 多个
form共用一个iframe时,后提交会中断前一个的load监听;建议每个form配独立name,或每次提交前移除旧监听器
Chrome 92+ 对长期 display:none 的 iframe 有加载降级策略,若 iframe 从未被插入过 DOM 或长时间未激活,form.submit() 可能直接报错 “The form owner is not in a Document”。这不是 bug,是浏览器主动防护——解决方法只有两个:确保 iframe 在提交前已挂载,或改用动态创建 + 即时插入的模式。



















