下載附件(image,doc,docx, excel,zip,pdf),應該是實際工做中常常遇到一個問題;這裏使用過幾種方式分享出來僅供參考; 初次寫可能存在問題,有問題望指出javascript
主要了解的幾個知識點:java
http 響應頭設置node
先來介紹經常使用方式: 這裏下載.doc文檔爲例,其它都相似後端
// 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 若是不存在,首先嚐試去預覽方式打開該文件 ,若是能就直接顯示不然以附件的形式下載並保存;瀏覽器
注意:指定在下載文件名中文狀況下,必須先進行編碼;微信
// 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
W3C 對 load 定義編碼
Type load Sync / Async Async Bubbles No Trusted Targets Window
,Document
,Element
適用對象:window,Document,Element 那麼對於咱們下載的文件並在其範圍;
若是須要捕獲文件下載的進度以及文件下載完成的狀態,須要使用下面的方式;
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文件內容亂碼等;