iframe 是兼容 ie9 及以下的唯一方案,需同域、target 与 name 一致,服务端返回可执行 html,动态创建 iframe 更安全。

form.submit() 配合 iframe 是唯一兼容 IE9 及以下的方案
现代浏览器用 FormData + fetch 就行,但若需支持 IE9 或老内核系统(如某些政务/金融专网),iframe 是唯一可行路径。它不是真异步,但能避免页面跳转,且原生支持 enctype="multipart/form-data" 文件上传。
关键约束必须满足:
-
iframe与主页面必须同域,否则iframe.contentWindow.document会触发跨域拒绝 -
form的target属性值必须严格等于iframe的name(不是id) - 服务端返回内容必须是完整 HTML,哪怕只有一行
<script></script>,不能只返回 JSON 或纯文本 - 多个
form共用同一iframe时,后提交的会中断前一个的load监听,导致回调丢失
清空表单字段必须等 iframe.load 完成后执行
在 form.onsubmit 里直接写 this.reset() 或 return false 都不行——前者会中断提交,后者根本发不出请求。正确时机是服务端响应到达、iframe 触发 load 事件之后。
常见错误写法:form.onsubmit = function() { this.reset(); return false; };
这会让表单完全不提交。
正确做法示例:
const iframe = document.querySelector('iframe[name="uploadFrame"]');
const form = document.querySelector('form');
<p>iframe.onload = function() {
// 读取响应内容
const doc = iframe.contentWindow.document;
const html = doc.body.innerHTML.trim();</p><p>// 清空字段(注意:不能用 reset(),它会重置所有控件包括 disabled 状态)
form.querySelectorAll('input, textarea, select').forEach(el => {
if (!el.hasAttribute('readonly') && !el.hasAttribute('disabled')) {
el.value = '';
}
});
};</p><p>form.addEventListener('submit', function(e) {
// 不阻止默认行为,让 form 正常提交到 iframe
});</p>
服务端返回内容必须可被 iframe 解析执行
浏览器加载 iframe 时,只关心是否成功渲染了 HTML 文档,不校验 HTTP 状态码。即使服务端返回 500,iframe.onload 仍会触发。因此错误状态必须靠响应体显式携带。
推荐返回格式(PHP/Node 示例):
<script type="text/javascript">
window.parent.handleUploadResult && window.parent.handleUploadResult({
status: 1,
msg: "上传成功",
url: "/uploads/abc.jpg"
});
</script>
前端需提前定义 window.handleUploadResult 函数,并确保 <script></script> 标签位于 内(部分浏览器对 head 中的脚本静默拦截)。
若返回纯 JSON 字符串(如 {"status":0,"msg":"文件过大"}),需手动解析:try { const res = JSON.parse(html); } catch(e) { /* 格式错误 */ }
动态创建 iframe 比复用更安全
多个表单共用一个 iframe 名称(如都设 target="uploadFrame")极易出问题:第二个提交会覆盖第一个的 onload,第一个永远收不到响应。
稳妥做法是每次提交前动态创建新 iframe:
- 生成唯一
name(如"uploadFrame_" + Date.now() + Math.random().toString(36).substr(2, 9)) - 插入到
document.body末尾(避免影响布局) - 提交完成后,在
iframe.onload里调用iframe.remove()防止内存泄漏
不要用 display:none 隐藏并反复复用——旧监听器残留、响应错乱、DOM 节点堆积都是真实发生过的线上问题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











