Ajax請求過程中下載文件在FireFox(火狐)瀏覽器下的兼容問題
需求很簡單,點(diǎn)擊一個文件鏈接下載該文件,同時向后臺發(fā)送請求。需求很常見,用戶點(diǎn)擊下載后通常要進(jìn)行下載量的統(tǒng)計(jì),統(tǒng)計(jì)的話可以利用 script標(biāo)簽 或者 img標(biāo)簽(圖片ping) 的跨域能力,將它們的 src 屬性指向統(tǒng)計(jì)地址,但是這次用了 ajax 進(jìn)行統(tǒng)計(jì),遂出現(xiàn)了這個問題。
demo 代碼如下:
<a id="a" href="http://c758482.r82.cf2.rackcdn.com/Sublime Text 2.0.2 x64 Setup.exe" >click</a> <script src="jQuery.js"></script> <script> document.getElementById("a").onclick = function(e) { $.post("data.php"); }; </script>
我們都知道,如果一個 a 標(biāo)簽同時擁有 onclick 事件和 href 屬性,onclick 事件的回調(diào)會在默認(rèn)事件(即跳轉(zhuǎn))之前執(zhí)行,這也正是可以在 onclick 事件中用類似 e.preventDefault() 的代碼去除默認(rèn)事件(即跳轉(zhuǎn))的原因。所以以上代碼,如果點(diǎn)擊 a 標(biāo)簽,首先會執(zhí)行 onclick 事件的回調(diào),即發(fā)送 ajax 請求,理論上,因?yàn)榇a中的 ajax 是異步的(其實(shí)同步也一樣),所以會一邊請求一邊打開下載文件。
chrome、UC、opera、2345瀏覽器中表現(xiàn)均和預(yù)期一致,firefox 下點(diǎn)擊能跳出下載文件,但是 ajax 部分報(bào)錯,IE 下未測試。
一開始的錯誤想法是,跨域?qū)е聢?bào)錯。當(dāng)點(diǎn)擊下載鏈接時,ajax 請求會以為頁面即將跳到 href 所指的地址,導(dǎo)致瀏覽器以為該 ajax 跨域。該錯誤想法很快被推翻,一是因?yàn)橄冗M(jìn)行 ajax 請求,所以請求瞬間并未跨域;二是并未報(bào)跨域錯誤(通常如果是跨域錯誤控制臺會指出);三是如下代碼更進(jìn)一步證明了該錯誤。
<a id="a" href="http://c758482.r82.cf2.rackcdn.com/Sublime Text 2.0.2 x64 Setup.exe" >click</a> <script src="jQuery.js"></script> <script> $.post("data.php"); // data.php sleep(100) </script>
打開該頁面,隨即進(jìn)行 ajax 請求,一旦點(diǎn)擊了下載按鈕,請求即被中止。如果 a 標(biāo)簽的 href 屬性值不是文件地址,而是用任意的一個 url 替換,如果點(diǎn)擊 a 標(biāo)簽,頁面會立即跳轉(zhuǎn)到該標(biāo)簽所指向的地址,頁面都不存在了,ajax 自然也就中斷了。如果 a 標(biāo)簽指向的是文件地址,在 ff 下是不是也會被一樣地解析呢(瀏覽器以為要跳到該地址了,而將 ajax 中止)?
答案是肯定的,我在 stackoverflow 中找到了答案。
When clicking the download link you are leaving the page, even it does not look so. If there would no file transfer, you would see the requested page.. try to set a target="_blank" or use an iframe as target for the link.
從提問可以看出,2010 年時 chrome 和 ff 都有類似的問題,而 chrome 或者說是 webkit 內(nèi)核的瀏覽器在之后的版本迭代中修復(fù)了這個問題, ff 則一直將問題留到了現(xiàn)在(個人認(rèn)為這不太合理)。
知道了問題的根源,解決方案也就呼之欲出了。
方法一:
最簡單的方法無非是給 a 標(biāo)簽加上 target="_blank",事實(shí)上,通常網(wǎng)頁都是這么做的,這也是值得肯定的做法。
方法二:
既然 a 標(biāo)簽的默認(rèn)行為會使得 ajax 請求中斷,那么將 "默認(rèn)行為" 放在請求之前呢?
<a id="a" href="javascript:;" >click</a> <script src="jQuery.js"></script> <script> document.getElementById("a").onclick = function(e) { location.href = "http://c758482.r82.cf2.rackcdn.com/Sublime Text 2.0.2 x64 Setup.exe"; $.post("data.php"); }; </script>
方法三:
設(shè)置定時器使請求延遲,但是因?yàn)?a 標(biāo)簽的默認(rèn)跳轉(zhuǎn)不屬于 Javascript 線程能控制的范圍,所以這個延遲閾值的設(shè)置非常重要,我本地測試結(jié)果居然是 2ms(也是萬萬沒想到),一般設(shè)置為 100ms 左右就 ok 了。 這個方法不優(yōu)雅,不應(yīng)該使用 。
<a id="a" href="http://c758482.r82.cf2.rackcdn.com/Sublime Text 2.0.2 x64 Setup.exe" >click</a> <script src="jQuery.js"></script> <script> document.getElementById("a").onclick = function(e) { setTimeout(function() { $.post("data.php"); }, 100); }; </script>
以上內(nèi)容給大家介紹了Ajax請求過程中下載文件在FireFox(火狐)瀏覽器下的兼容問題,希望對大家今后的工作學(xué)習(xí)有所幫助。
相關(guān)文章
基于iframe實(shí)現(xiàn)ajax跨域請求 獲取網(wǎng)頁中ajax數(shù)據(jù)
這篇文章主要介紹了基于iframe實(shí)現(xiàn)ajax跨域請求,并獲取網(wǎng)頁中ajax數(shù)據(jù),如何利用網(wǎng)頁ajax請求暴露出來的接口去抓取網(wǎng)頁數(shù)據(jù)?需要的朋友可以參考下2016-01-01讓ajax更加友好的實(shí)現(xiàn)方法(實(shí)時顯示后臺處理進(jìn)度。)
我們能否讓ajax更加友好點(diǎn),實(shí)時顯示服務(wù)器處理的進(jìn)度了?這在一些長時間的請求中尤其重要,比如上傳文件、發(fā)送郵件、批量處理數(shù)據(jù)。2010-06-06使用AJAX進(jìn)行WEB應(yīng)用程序開發(fā)的方法
AJAX,一個異步JavaScript和XML的縮略詞,是最近出來的技術(shù)詞語。異步意味著你可以經(jīng)由超文本傳輸協(xié)議(HTTP)向一個服務(wù)器發(fā)出請求并且在等待該響應(yīng)時繼續(xù)處理另外的數(shù)據(jù)。2010-04-04ajax實(shí)時任務(wù)提示功能的實(shí)現(xiàn)代碼
本項(xiàng)目運(yùn)用了 FLEAPHP,MYSQL,SMARTY,FCKEDItor,JSON,PROTOTYPE的技術(shù),在這里首先要感謝這些開源項(xiàng)目的開發(fā)者給我們帶來的好東西,其次要感謝[生氣豬--讓我?guī)退鲆粋€這樣的小東西來提醒她按時完成事情].花了一個3個小時完成.希望給大家起到拋磚引玉的作用啊....2008-09-09AJAX初體驗(yàn)之實(shí)戰(zhàn)篇——打造博客無刷新搜索
AJAX初體驗(yàn)之實(shí)戰(zhàn)篇——打造博客無刷新搜索...2006-08-08AJAX實(shí)現(xiàn)web頁面中級聯(lián)菜單的設(shè)計(jì)
AJAX實(shí)現(xiàn)web頁面中級聯(lián)菜單的設(shè)計(jì)...2007-03-03巧用ajax請求服務(wù)器加載數(shù)據(jù)列表時提示loading的方法
下面小編就為大家?guī)硪黄捎胊jax請求服務(wù)器加載數(shù)據(jù)列表時提示loading的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04利用ajax+php實(shí)現(xiàn)商品價格計(jì)算
這篇文章主要為大家詳細(xì)介紹了利用ajax+php實(shí)現(xiàn)商品價格計(jì)算,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-03-03