JS下載文件經常使用的方式

下載附件(image,doc,docx, excel,zip,pdf),應該是實際工做中常常遇到一個問題;這裏使用過幾種方式分享出來僅供參考; 初次寫可能存在問題,有問題望指出javascript

​ 主要了解的幾個知識點:java

先來介紹經常使用方式: 這裏下載.doc文檔爲例,其它都相似後端

利用 iframe 或 a 鏈接

服務端代碼

// nodejs
const http = require('http');
const fs = require('fs');
const path = require('path');
http.createServer(function (req, res) { 
    let filename = encodeURIComponent('微信多開的步驟.doc');
    // 下面兩個主要在跨域狀況下,須要設置的
    res.setHeader('Access-Control-Allow-Origin', '*');
     res.setHeader('Access-Control-Expose-Headers', 'Content-Disposition');
    
    // 設置響應頭
    res.setHeader('Content-Type', 'application/zip;charset=UTF-8');
    res.setHeader('Content-Disposition', `attachment; filename=${filename}`);
    let fs.readFile(path.resolve(__dirname, `./微信多開的步驟.doc`), function (err, data) {
      if (err) throw err;
      res.end(data);});
}).listen(3000);

Content-Disposition 消息頭指示回覆的內容該以何種形式展現,是以內聯的形式(即網頁或者頁面的一部分),仍是以附件的形式下載並保存到本地。跨域

​ 大概流程:
​ 1 下載時瀏覽器會嘗試去找下響應頭中 Content-Disposition
​ 2 若是不存在,首先嚐試去預覽方式打開該文件 ,若是能就直接顯示不然以附件的形式下載並保存;瀏覽器

注意:指定在下載文件名中文狀況下,必須先進行編碼;微信

JS

// iframe 
var downloadFileUrl = "http://localhost:3000"
var elemIF = document.createElement("iframe");
elemIF.src = downloadFileUrl;
elemIF.style.display = "none";
document.body.appendChild(elemIF);

// a 
var a = document.createElement('a');
a.href = downloadFileUrl;
a.click();

上述兩種方式僅僅就是發送一個請求,主要依賴後端的支持;對不須要精確知道文件下載的狀態,上面方式就能知足下載;app

你們可能有疑問,iframe 不是能夠經過 onload 來捕獲加載的完成狀態 ?
先來看看 load 適用哪些對象?ui

load

​ W3C 對 load 定義編碼

Type load
Sync / Async Async
Bubbles No
Trusted Targets Window, Document, Element

適用對象:window,Document,Element 那麼對於咱們下載的文件並在其範圍;

若是須要捕獲文件下載的進度以及文件下載完成的狀態,須要使用下面的方式;

XMLHttpRequest

var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onprogress = function (event) {
    console.log(Math.round(event.loaded / event.total * 100) + "%");
};
xhr.responseType = 'arraybuffer';
xhr.addEventListener('readystatechange', function (event) {
    if (xhr.status === 200 && xhr.readyState === 4) {
        // 獲取響應頭主要獲取附件名稱
        var contentDisposition = xhr.getResponseHeader('content-disposition');
        // 獲取類型類型和編碼  
        var contentType = xhr.getResponseHeader('content-type');
        // 構造blob對象,具體看頭部提供的連接地址
        var blob = new Blob([xhr.response], {
            type: contentType
        });
        var url = window.URL.createObjectURL(blob);
        // 獲取文件夾名
        var regex = /filename=[^;]*/;
        var matchs = contentDisposition.match(regex);
        if (matchs) {
            filename = decodeURIComponent(matchs[0].split("=")[1]);
        } else {
            filename = +Date.now() + ".doc";
        }
        var a = document.createElement('a');
        a.href = url;
        a.download = filename;
        a.click();
        window.URL.revokeObjectURL(url);
        // dosomething
    }
})
xhr.send();

上述對比第一種方式,經過 onprogress 捕獲下載進度(界面經過顯示進度條來提高體驗);經過 readystatechange 監聽下載完後並能夠作其它的事情;

注意: 必須指定 responseType 類型,能夠是arraybuffer 或 blob 不然會出現錯誤問題 好比 zip,pdf文件下載以後打不開提示錯誤的格式; .doc,.excel文件內容亂碼等;

相關文章
相關標籤/搜索