国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

瀏覽器端下載那些事

3fuyu / 1303人閱讀

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

一、背景

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

1、讀取form里的數據

2、向服務端發請求,并下載文件;要求拿到請求狀態,如果出錯及時反饋給用戶。

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

二、一般下載文件方式

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

1、window.open(url);

2、window.location.href = url;

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

4、a 標簽,利用download屬性

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

1、window.open(url)

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

2、window.location.href

頁面將跳轉到一個錯誤頁面

3、iframe

用戶感知不到任何變化

4、a標簽

直接出現 下載失敗

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

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

三、瀏覽器FileAPI方式

相信大家對blob這個對象也不太陌生,它是html5標準里的一個二進制數據對象,可以與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,就可以實現瀏覽器端自己的下載了。那如何從服務端拿到數據,并下載呢?

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

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

四、額外收獲-進度條

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

關于進度條,我們可以利用fetch配合reader對象來實現進度條功能,如下:

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這個對象來實現,會更簡單直接一點。

五、常見問題 1、filename

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

2、cors

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

3、大文件下載問題

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

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

五、總結

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79439.html

相關文章

  • 聊聊Ajax那些

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

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

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

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

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

    BigTomato 評論0 收藏0

發表評論

0條評論

3fuyu

|高級講師

TA的文章

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