IE6中请求莫名中断(条件:a标签,click事件中有ajax请求,a标签中有href且是JavaScript:void(0);或JavaScript:;等阻断跳转代码)

文章详细介绍了在IE6浏览器中使用a标签触发AJAX请求时出现请求被中断的问题,并给出了具体的解决办法。通过阻止a标签的默认行为可以避免中断AJAX请求。

原载于:雨夜带刀's Blog
本文链接:http://stylechen.com/ie6-aborted-ajax.html

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
  var url = "http://api.flickr.com/services/"
    "feeds/photos_public.gne?tags=car&"
    "tagmode=any&format=json&jsoncallback=?";
  $( "#btn" ).click(function(){
    $.getJSON( url, function( data ){
      alert(  data );
    });   });
</script>

在IE6中使用Fiddler2监视请求,经常会出现”aborted”,折腾了许久,相当的诡异。后来将a标签换成button,请求正常,最后经提醒,可能是a标签的默认事件中断了请求。但是,在HTML代码中,已经将a标签的href设置成了”javascript:;”,通常这样是可以阻止默认事件了(页面跳转)。a标签的click事件会先执行,然后才执行href的跳转,如果href是一段javascript语句,这个时候就会执行。IE6在执行href的javascript语句时就中断了click触发的ajax请求。使用href=”javascript:;”是为了阻止默认事件,将阻止默认事件的动作移到click事件中就可以解决问题了,这样就不会执行href中的javascript语句了。


$( "#btn" ).click(function(e){
    $.getJSON( url, function( data ){
           alert( data );
    });
   e.preventDefault();
});

结合下自己遇到的情况代码如下:
html代码如下:
<a class="js_statrPrize" text="go" href="javascript:void(0);">报名参加</a>

js代码如下:



$(".js_statrPrize").click(function () {
        $.ajax({
            url:urls.loginUrl,
            type:"get",
            dataType:"jsonp",
            jsonp:"jsoncallback",
            data:{
                r:Math.random()
            },
            success:function(d){
                if (d.IsSuccess) {
                    if (defaults.successFn) {
                        defaults.successFn(d);
                    }
                } else {
                    if (defaults.failFn) {
                        defaults.failFn(d);
                    }
                }
            },
            error:function(){
                alert("程序错误");
            }
        });
    });

在ie6下直接走error了,一点击这个按钮直接alert“程序出错”;从昨天一直翻到今天终于找到了本文的答案。



<think> 我们无法直接使用a标签href属性发送POST请求来实现下载,因为a标签默认是GET请求。但我们可以通过以下两种方法模拟POST下载: ### 方法一:使用JavaScript动态创建表单(同步下载) 这种方法适用于需要传递复杂参数避免URL长度限制的场景: ```html <a href="javascript:void(0)" onclick="downloadByPost()">下载文件</a> <script> function downloadByPost() { const form = document.createElement(&#39;form&#39;); form.method = &#39;POST&#39;; form.action = &#39;your-download-api&#39;; // 替换为下载接口 // 添加POST参数 const data = { fileName: &#39;报告.pdf&#39;, userId: 123 }; Object.entries(data).forEach(([key, value]) => { const input = document.createElement(&#39;input&#39;); input.type = &#39;hidden&#39;; input.name = key; input.value = value; form.appendChild(input); }); document.body.appendChild(form); form.submit(); // 自动提交表单触发下载 document.body.removeChild(form); } </script> ``` **原理**: 1. 创建隐藏表单并设置`method="POST"` 2. 动态添加需要POST提交的参数 3. 提交表单后,后端返回文件流时浏览器自动触发下载[^1] --- ### 方法二:使用Fetch API + Blob(异步下载) 这种方法可在下载前进行预处理,适用于需要先获取文件名等元数据的场景: ```html <a href="javascript:void(0)" onclick="fetchDownload()">异步下载</a> <script> async function fetchDownload() { const response = await fetch(&#39;your-api&#39;, { method: &#39;POST&#39;, headers: { &#39;Content-Type&#39;: &#39;application/json&#39; }, body: JSON.stringify({ fileName: &#39;data.zip&#39; }) // POST参数 }); // 从响应头获取文件名 const filename = response.headers.get(&#39;Content-Disposition&#39;)?.split(&#39;filename=&#39;)[1] || &#39;file.bin&#39;; // 转换为Blob并创建下载链接 const blob = await response.blob(); const url = URL.createObjectURL(blob); const a = document.createElement(&#39;a&#39;); a.href = url; a.download = decodeURIComponent(filename); // 处理中文文件名 a.click(); // 释放内存 URL.revokeObjectURL(url); } </script> ``` **优势**: - 可自定义请求头 - 支持现代异步流程控制 - 可精确处理文件名等元信息[^1][^2] --- ### 关键差异对比 | 方法 | 同步表单提交 | Fetch+Blob | |--------------|---------------------------|--------------------------| | 请求类型 | 原生表单提交 | AJAX请求 | | 页面跳转 | 会刷新/跳转页面 | 纯后台操作无页面跳转 | | 数据处理 | 直接返回文件流 | 需手动处理Blob对象 | | 浏览器兼容性 | 所有浏览器 | 不支持IE11以下 | | 安全性 | 需防范CSRF | 需处理CORS | > ⚠️ 注意:Fetch方案在下载大文件时可能占用大量内存,建议超过100MB的文件使用表单提交方案[^1][^4] --- ### 常见问题解决 1. **中文文件名乱码**: ```javascript // 从Content-Disposition解析时应处理编码 const rawName = header.split(&#39;filename*=&#39;)[1]; const decodedName = rawName ? decodeURIComponent(rawName.split("&#39;&#39;")[1]) : defaultName; ``` 2. **跨域问题**: 服务端需设置响应头: ```http Access-Control-Allow-Origin: * Access-Control-Expose-Headers: Content-Disposition ``` 3. **CSRF防护**: 在表单/Fetch请求中添加CSRF Token: ```javascript // 表单添加 const csrfInput = `<input type="hidden" name="_csrf" value="${token}">`; // Fetch添加 headers: { &#39;X-CSRF-Token&#39;: csrfToken } ``` --- §§相关问题§§ 1. 如何实现大文件的分片下载? 2. 服务端如何设置才能让浏览器自动触发下载? 3. 前端如何显示下载进度条? 4. 在React中如何封装通用下载组件? [^1]: 使用Blob对象接收处理文件数据 [^2]: 通过a标签的download属性实现下载命名 [^3]: 处理URL特殊字符的编码问题 [^4]: 使用iframe实现批量下载 </think># 使用a标签通过POST请求实现文件下载的方法 虽然a标签href属性默认只支持GET请求,但我们可以通过JavaScript实现POST请求下载文件。以下是两种最常用的实现方法: ## 方法一:动态创建表单提交(同步下载) 这是最直接的方式,通过JavaScript动态创建表单并提交: ```html <a href="#" onclick="downloadByPost(); return false;">下载文件</a> <script> function downloadByPost() { // 创建隐藏表单 const form = document.createElement(&#39;form&#39;); form.method = &#39;POST&#39;; form.action = &#39;/your-download-api&#39;; // 替换为你的下载接口 // 添加POST参数 const data = { fileName: &#39;report.pdf&#39;, userId: 123 }; Object.entries(data).forEach(([key, value]) => { const input = document.createElement(&#39;input&#39;); input.type = &#39;hidden&#39;; input.name = key; input.value = value; form.appendChild(input); }); // 提交表单 document.body.appendChild(form); form.submit(); document.body.removeChild(form); } </script> ``` **实现原理**: 1. 创建隐藏的表单元素 2. 设置`method="POST"`和`action`属性为目标URL 3. 添加隐藏的input字段作为POST参数 4. 提交表单触发下载[^3] ## 方法二:Fetch API + Blob(异步下载) 对于需要处理响应数据需要更多控制的场景,可以使用Fetch API: ```html <a href="#" onclick="fetchDownload(); return false;">异步下载</a> <script> async function fetchDownload() { try { const response = await fetch(&#39;/your-download-api&#39;, { method: &#39;POST&#39;, headers: { &#39;Content-Type&#39;: &#39;application/json&#39; }, body: JSON.stringify({ fileName: &#39;data.zip&#39; }) // POST数据 }); // 从响应头获取文件名 const contentDisposition = response.headers.get(&#39;Content-Disposition&#39;); const filename = contentDisposition ? contentDisposition.split(&#39;filename=&#39;)[1] : &#39;download.bin&#39;; // 转换为Blob并创建下载链接 const blob = await response.blob(); const url = URL.createObjectURL(blob); const a = document.createElement(&#39;a&#39;); a.href = url; a.download = decodeURIComponent(filename); // 处理中文文件名 a.click(); // 清理资源 URL.revokeObjectURL(url); } catch (error) { console.error(&#39;下载失败:&#39;, error); } } </script> ``` **优势**: 1. 完全控制请求和响应过程 2. 可以从响应头解析文件名 3. 支持处理二进制数据 4. 不会导致页面刷新[^1][^2] ## 批量下载实现(使用iframe) 如果需要批量下载多个文件,可以使用iframe方法: ```javascript function batchDownload(items) { items.forEach(item => { const iframe = document.createElement(&#39;iframe&#39;); // 创建隐藏表单 const form = document.createElement(&#39;form&#39;); form.method = &#39;POST&#39;; form.action = &#39;/download-api&#39;; form.target = iframe.name; // 添加参数 const input = document.createElement(&#39;input&#39;); input.type = &#39;hidden&#39;; input.name = &#39;fileId&#39;; input.value = item.id; form.appendChild(input); document.body.appendChild(iframe); document.body.appendChild(form); form.submit(); // 清理 setTimeout(() => { document.body.removeChild(iframe); document.body.removeChild(form); }, 5000); }); } ``` ## 关键注意事项 1. **文件名处理**: ```javascript // 处理Content-Disposition中的文件名 const decodeFilename = (header) => { const match = header.match(/filename\*?=[&#39;"]?(?:UTF-\d[&#39;"]*)?([^;\r\n"&#39;]*)[&#39;"]?/i); return match ? decodeURIComponent(match[1]) : &#39;download&#39;; }; ``` 2. **大文件处理**: - 使用流式处理避免内存溢出 - 显示下载进度条 3. **安全考虑**: - 添加CSRF令牌 - 验证用户权限 - 限制下载频率 4. **浏览器兼容性**: - Fetch API需要现代浏览器支持 - 对于IE等旧浏览器,使用XMLHttpRequest替代 ## 适用场景对比 | 方法 | 适用场景 | 优点 | 缺点 | |---------------------|-----------------------------------|--------------------------|--------------------| | 动态表单提交 | 简单下载,不依赖现代API | 兼容性好,实现简单 | 无法处理响应头信息 | | Fetch API + Blob | 需要控制下载过程,获取文件信息 | 完全控制,功能强大 | 较复杂,需现代浏览器 | | iframe批量下载 | 同时下载多个文件 | 不阻塞UI,可并行处理 | 资源占用较多 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值