Ajax请求过程中下载文件在FireFox(火狐)浏览器下的兼容问题
需求很简单,点击一个文件链接下载该文件,同时向后台发送请求。需求很常见,用户点击下载后通常要进行下载量的统计,统计的话可以利用script标签或者img标签(图片ping)的跨域能力,将它们的src属性指向统计地址,但是这次用了ajax进行统计,遂出现了这个问题。
demo代码如下:
<aid="a"href="http://c758482.r82.cf2.rackcdn.com/SublimeText2.0.2x64Setup.exe">click</a> <scriptsrc="jQuery.js"></script> <script> document.getElementById("a").onclick=function(e){ $.post("data.php"); }; </script>
我们都知道,如果一个a标签同时拥有onclick事件和href属性,onclick事件的回调会在默认事件(即跳转)之前执行,这也正是可以在onclick事件中用类似e.preventDefault()的代码去除默认事件(即跳转)的原因。所以以上代码,如果点击a标签,首先会执行onclick事件的回调,即发送ajax请求,理论上,因为代码中的ajax是异步的(其实同步也一样),所以会一边请求一边打开下载文件。
chrome、UC、opera、2345浏览器中表现均和预期一致,firefox下点击能跳出下载文件,但是ajax部分报错,IE下未测试。
一开始的错误想法是,跨域导致报错。当点击下载链接时,ajax请求会以为页面即将跳到href所指的地址,导致浏览器以为该ajax跨域。该错误想法很快被推翻,一是因为先进行ajax请求,所以请求瞬间并未跨域;二是并未报跨域错误(通常如果是跨域错误控制台会指出);三是如下代码更进一步证明了该错误。
<aid="a"href="http://c758482.r82.cf2.rackcdn.com/SublimeText2.0.2x64Setup.exe">click</a> <scriptsrc="jQuery.js"></script> <script> $.post("data.php");//data.phpsleep(100) </script>
打开该页面,随即进行ajax请求,一旦点击了下载按钮,请求即被中止。如果a标签的href属性值不是文件地址,而是用任意的一个url替换,如果点击a标签,页面会立即跳转到该标签所指向的地址,页面都不存在了,ajax自然也就中断了。如果a标签指向的是文件地址,在ff下是不是也会被一样地解析呢(浏览器以为要跳到该地址了,而将ajax中止)?
答案是肯定的,我在stackoverflow中找到了答案。
Whenclickingthedownloadlinkyouareleavingthepage,evenitdoesnotlookso.Iftherewouldnofiletransfer,youwouldseetherequestedpage..trytosetatarget="_blank"oruseaniframeastargetforthelink.
从提问可以看出,2010年时chrome和ff都有类似的问题,而chrome或者说是webkit内核的浏览器在之后的版本迭代中修复了这个问题,ff则一直将问题留到了现在(个人认为这不太合理)。
知道了问题的根源,解决方案也就呼之欲出了。
方法一:
最简单的方法无非是给a标签加上target="_blank",事实上,通常网页都是这么做的,这也是值得肯定的做法。
方法二:
既然a标签的默认行为会使得ajax请求中断,那么将"默认行为"放在请求之前呢?
<aid="a"href="javascript:;">click</a> <scriptsrc="jQuery.js"></script> <script> document.getElementById("a").onclick=function(e){ location.href="http://c758482.r82.cf2.rackcdn.com/SublimeText2.0.2x64Setup.exe"; $.post("data.php"); }; </script>
方法三:
设置定时器使请求延迟,但是因为a标签的默认跳转不属于Javascript线程能控制的范围,所以这个延迟阈值的设置非常重要,我本地测试结果居然是2ms(也是万万没想到),一般设置为100ms左右就ok了。这个方法不优雅,不应该使用。
<aid="a"href="http://c758482.r82.cf2.rackcdn.com/SublimeText2.0.2x64Setup.exe">click</a> <scriptsrc="jQuery.js"></script> <script> document.getElementById("a").onclick=function(e){ setTimeout(function(){ $.post("data.php"); },100); }; </script>
以上内容给大家介绍了Ajax请求过程中下载文件在FireFox(火狐)浏览器下的兼容问题,希望对大家今后的工作学习有所帮助。