成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

瀏覽器端下載那些事

3fuyu / 1313人閱讀

摘要:三瀏覽器方式相信大家對這個對象也不太陌生,它是標準里的一個二進制數(shù)據(jù)對象,可以與對象配合,進行文件的下載。其實這樣一個簡單的,就可以實現(xiàn)瀏覽器端自己的下載了。

一、背景

最近寫了一個react的組件,用來做文件導出。環(huán)境是ie10+。
細一點說,就是

1、讀取form里的數(shù)據(jù)

2、向服務(wù)端發(fā)請求,并下載文件;要求拿到請求狀態(tài),如果出錯及時反饋給用戶。

第一個需求,我們借用了jquery的serializeArray方法,畢竟我們不想再造輪子。那接下來重點說說后面的需求。

二、一般下載文件方式

大家在下載的問題的時候,一般來說,會用到

1、window.open(url);

2、window.location.href = url;

3、iframe,其實與window.open類似,但不用開啟新的tab

4、a 標簽,利用download屬性

這些方法,其實極度依賴服務(wù)端的正確性。我們可以看看服務(wù)端一旦出錯的結(jié)果。

1、window.open(url)

打開一個帶錯誤信息的頁面

2、window.location.href

頁面將跳轉(zhuǎn)到一個錯誤頁面

3、iframe

用戶感知不到任何變化

4、a標簽

直接出現(xiàn) 下載失敗

當然,如果response header里有content-disposition字段的話,瀏覽器都會下載一個帶錯誤信息的文件。這時候,其實我們可以多發(fā)一個ajax/fetch請求,先檢測下接口狀態(tài),然后再取做下載邏輯。但這樣就對服務(wù)器造成了額外的開銷。

這樣的體驗都不太好,作為一個追求極致體驗的程序猿,我們應(yīng)該重新思考下,如何提升用戶體驗。

三、瀏覽器FileAPI方式

相信大家對blob這個對象也不太陌生,它是html5標準里的一個二進制數(shù)據(jù)對象,可以與URL 對象配合,進行文件的下載。

下面是一個最簡單的demo(我們暫時不考慮瀏覽器兼容問題)。

let blob2 = new Blob(["123"]);
let url = URL.createObjectURL(blob2);
let a = document.createElement("a");
a.download = "test";
a.href = url;
a.click();

其實這樣一個簡單的demo,就可以實現(xiàn)瀏覽器端自己的下載了。那如何從服務(wù)端拿到數(shù)據(jù),并下載呢?

這里,我們拿服務(wù)端數(shù)據(jù),主要是通過fetch,fetch提供了一些api。其中就有一個blob的promise,我們可以把返回的數(shù)據(jù)轉(zhuǎn)成blob對象,這樣就能去下載文件了。

回到最初的需求,我們需要檢測接口的狀態(tài)。其實通過fetch,我們完全可以拿到response的信息,既然都能拿到,那控制權(quán)就在我們自手上了。

四、額外收獲-進度條

按照FileApi的方式,我們是一次性從服務(wù)端拿到數(shù)據(jù),然后再在瀏覽器端進行操作。既然是這樣,那拿數(shù)據(jù)的過程是不是就可以顯示出進度呢?這個特性,我們用以前傳統(tǒng)的下載方式是完全做不到的。

關(guān)于進度條,我們可以利用fetch配合reader對象來實現(xiàn)進度條功能,如下:

fetch(url).then(response => {

  var reader = response.body.getReader();
  var headers = response.headers;
  var totalLength = headers.get("Content-Length");
  var bytesReceived = 0;

  reader.read().then(function processResult(result) {
    if (result.done) {
      return;
    }

    bytesReceived += result.value.length;
    console.log(`progress: ${bytesReceived / totalLength * 100}%`);

    return reader.read().then(processResult);
  });
});

當然,有人可能會說ie下fetch會有問題。沒錯,確實會有問題,但這時候我們可以用XMLHttpRequest這個對象來實現(xiàn),會更簡單直接一點。

五、常見問題 1、filename

通過fileapi的方式下載文件,有個很重要的問題,就是文件名。最初的一些下載方式,都是瀏覽器自己通過判斷content-disposition這個字段來讀取文件名。那現(xiàn)在不一樣了,我們需要自己來讀取文件名,這時候難免要自己讀這個header,通過正則匹配下文件名。

2、cors

關(guān)于cors問題,其實只要是異步請求,都會碰到。新版瀏覽器,我們常用access-control-allow-origin這個字段來解決跨域問題。這時候,我們在讀文件名的可能要留一點,記得在header里加上Access-Control-Expose-Headers這個字段,不然fetch是取不到filename信息的。具體可以看看這篇doc

3、大文件下載問題

在用fileapi的時候,我們發(fā)現(xiàn)文件過大會讓瀏覽器崩潰,會導致文件下載失敗。目前我在測試500mb以上的文件的時候就會碰到這樣的情況。這個問題,可以通過webkitrequestfilesystem這個對象來曲線解決,但這并不是一個standard api,目前只有新版chrome支持這個對象,所以盡量不要去用。

我們推薦在拿到response的時候,讀取一下blob的size,如果發(fā)現(xiàn)太大,就進行降級處理,使用我們最初的那中方式。

五、總結(jié)

我一直相信no silver bullet這句話,雖然fileapi這種方式能解決部分問題,但其實也有很多缺點,相信大家會在實際場景中會更深刻的感受到。所以在設(shè)計組件的時候,我們在做好優(yōu)雅降級的方案同時,還特意為大家開放了各種下載方式,以適應(yīng)各種場景。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79439.html

相關(guān)文章

  • 聊聊Ajax那些

    摘要:年初,許多事件使得被大眾所接受。這使得應(yīng)用程序更為迅捷地響應(yīng)用戶交互,并避免了在網(wǎng)絡(luò)上發(fā)送那些沒有改變的信息,減少用戶等待時間,帶來非常好的用戶體驗。調(diào)用方法后立即觸發(fā),若未被調(diào)用則不會觸發(fā)此事件。 了解Ajax的起源、概念及特點 起源 該技術(shù)在1998年前后得到了應(yīng)用。允許客戶端腳本發(fā)送HTTP請求(XMLHTTP)的第一個組件由Outlook Web Access小組寫成。該組...

    v1 評論0 收藏0
  • 聊聊Ajax那些

    摘要:年初,許多事件使得被大眾所接受。這使得應(yīng)用程序更為迅捷地響應(yīng)用戶交互,并避免了在網(wǎng)絡(luò)上發(fā)送那些沒有改變的信息,減少用戶等待時間,帶來非常好的用戶體驗。調(diào)用方法后立即觸發(fā),若未被調(diào)用則不會觸發(fā)此事件。 了解Ajax的起源、概念及特點 起源 該技術(shù)在1998年前后得到了應(yīng)用。允許客戶端腳本發(fā)送HTTP請求(XMLHTTP)的第一個組件由Outlook Web Access小組寫成。該組...

    xzavier 評論0 收藏0
  • 聊聊Ajax那些

    摘要:年初,許多事件使得被大眾所接受。這使得應(yīng)用程序更為迅捷地響應(yīng)用戶交互,并避免了在網(wǎng)絡(luò)上發(fā)送那些沒有改變的信息,減少用戶等待時間,帶來非常好的用戶體驗。調(diào)用方法后立即觸發(fā),若未被調(diào)用則不會觸發(fā)此事件。 了解Ajax的起源、概念及特點 起源 該技術(shù)在1998年前后得到了應(yīng)用。允許客戶端腳本發(fā)送HTTP請求(XMLHTTP)的第一個組件由Outlook Web Access小組寫成。該組...

    BigTomato 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<