如何在IE7中使用XMLHttpRequest发送POST请求及解决send报错问题
嘿,哥们儿,IE7这个老古董的坑确实够头疼的!我来帮你拆解一下你遇到的两个问题——IE7里用XMLHttpRequest发POST,还有上传二进制文件时的「无效参数」错误。
一、先搞懂IE7里的XMLHttpRequest到底是什么
IE7根本不支持标准的new XMLHttpRequest()构造函数,它用的是ActiveX控件Microsoft.XMLHTTP。而且更关键的是:IE7完全没有FormData接口,你代码里自己定义的formData只是个普通JS对象,xhr.send()根本不知道怎么处理它,这就是你报「无效参数」的核心原因!
二、报错原因详细分析
你写的代码里有三个致命问题:
- 你用了
new XMLHttpRequest()在IE7里创建对象,虽然部分IE7版本可能兼容,但本质上它不是标准实现; - 你把自定义的
formData对象传给xhr.send(),但IE7的XHR(包括ActiveX版本)只支持发送字符串、Blob(但IE7也不支持Blob),或者表单格式的编码字符串,完全不认识你自己定义的对象结构; - 最要命的是:IE7无法通过XHR直接上传二进制文件,它没有读取文件二进制内容的API,也没法构建正确的
multipart/form-data请求体。
三、解决方案分两种情况
1. 普通POST请求(非文件/二进制数据)
如果只是发普通的表单数据,不用传文件,你可以这么写:
// 兼容IE7的XHR创建方式 var xhr; try { // 标准浏览器写法 xhr = new XMLHttpRequest(); } catch(e) { // IE7及以下用ActiveX控件 xhr = new ActiveXObject("Microsoft.XMLHTTP"); } xhr.open('POST', config.javaServer+config.baseUrl+AccountNumber+"/upload/"+config.lowerClaimDocUplTs, true); // 设置普通POST请求的Content-Type xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.setRequestHeader('claimNum', ClaimNumber); // IE7用onreadystatechange而不是onload xhr.onreadystatechange = function() { if(xhr.readyState === 4 && xhr.status === 200) { // 处理返回结果 var response = xhr.responseText; // do something to response... } }; // 把bodyValues转成urlencoded格式的字符串 var postData = []; for(var key in bodyValues) { if(bodyValues.hasOwnProperty(key)) { postData.push(encodeURIComponent(key) + '=' + encodeURIComponent(bodyValues[key])); } } xhr.send(postData.join('&'));
2. 上传二进制文件(你的核心问题)
刚才说了,IE7没法用XHR直接传文件,唯一可行的方案是用隐藏iframe模拟异步上传——通过表单提交到iframe里,这样页面不会刷新,还能拿到返回结果。
步骤1:先写HTML结构
<!-- 隐藏的iframe,用来接收上传结果,不会刷新页面 --> <iframe id="uploadFrame" name="uploadFrame" style="display: none;"></iframe> <!-- 用于上传的表单,target指向上面的iframe --> <form id="uploadForm" method="POST" enctype="multipart/form-data" target="uploadFrame"> <!-- 存放claimNum的隐藏字段 --> <input type="hidden" name="claimNum" id="claimNumInput"> <!-- 其他需要提交的body数据,后面用JS动态添加 --> </form>
步骤2:JS处理上传逻辑
// 监听iframe加载完成,获取服务器返回的结果 document.getElementById('uploadFrame').onload = function() { // 兼容IE7的文档获取方式 var doc = this.contentDocument || this.contentWindow.document; var responseText = doc.body.textContent || doc.innerText; try { // 把返回的字符串转成JSON(如果服务器返回JSON的话) var result = JSON.parse(responseText); // 这里处理你的业务逻辑,比如回调 // do something to response... } catch(err) { console.error('解析返回结果失败:', err); } }; // 上传函数 function uploadFile(options) { var form = document.getElementById('uploadForm'); // 设置表单的提交地址 form.action = config.javaServer + config.baseUrl + AccountNumber + "/upload/" + config.lowerClaimDocUplTs; // 设置claimNum的值 document.getElementById('claimNumInput').value = ClaimNumber; // 动态添加bodyValues里的其他字段 var bodyValues = options[0]; delete bodyValues.file; // 移除文件字段,因为文件用input[type=file]处理 for(var key in bodyValues) { if(bodyValues.hasOwnProperty(key)) { var input = document.createElement('input'); input.type = 'hidden'; input.name = key; input.value = bodyValues[key]; form.appendChild(input); } } // 添加文件输入框(如果页面上没有的话) var fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.name = 'files'; fileInput.style.display = 'none'; // 当用户选择文件后自动提交表单 fileInput.onchange = function() { form.submit(); // 提交后移除临时的fileInput,避免重复添加 form.removeChild(fileInput); }; form.appendChild(fileInput); // 触发文件选择框(IE7里需要模拟点击) fileInput.click(); } // 调用上传函数,传入你的options参数 uploadFile(options);
注意事项
- IE7里的文件输入框不能通过JS直接设置value,必须让用户手动选择文件,所以上面的代码是创建临时fileInput,触发点击让用户选择;
- 服务器端要支持
multipart/form-data格式的请求,和普通表单上传的处理逻辑一致; - 如果需要多次上传,记得每次提交后清理表单里的动态添加的字段,避免重复提交。
内容的提问来源于stack exchange,提问作者Naveen Asapu
相关产品推荐
相关产品推荐

