所以需要解決 Cross Domain 資料存取的限制。
解決辦法為採用 XMLHttpRequest 物件來突破跨區存取限制。
直接看 Code
downloadFile = function( _fileUrl ) { var xhr = new XMLHttpRequest(); if ("withCredentials" in xhr) { xhr.open('GET', _fileUrl, true); } else if (typeof XDomainRequest != "undefined") { xhr = new XDomainRequest(); xhr.open('GET', _fileUrl ); } xhr.responseType = "blob"; xhr.onreadystatechange = function () { if (xhr.readyState == 4) { var a = document.createElement('a'); a.href = window.URL.createObjectURL(xhr.response); a.download = fileName; a.click(); } }; xhr.send(); }
downloadFile 這個函式接收一個參數 _fileUrl 指出檔案路徑
var xhr = new XMLHttpRequest() 建立一個 xhr 物件
withCredentials這個屬性預設為false,
因為 XMLHTTPRequest2 物件才允許CORS(Cross-Origin Resource Sharing),
所以檢查是否有支援withCredentials屬性,
該屬性指示是否使用如cookie或授權標頭檔等憑證進行跨站存取控制(cross-site Access-Control)請求。
而IE 8與IE 9只能使用 XDomainRequest 物件處理 CORS 請求(IE8,9不支援XHR2)
responseType 屬性指定回應狀態,
可以為 blob, json, text 等等,
為了方便後續創造連結,所以指定回應狀態為"blob"
onreadystatechange 這個函式會在 readyState 屬性改變時被呼叫
而 readyState 屬性值為 4 時,表示作業完成。
此時便可以創造一個元素 a,並且呼叫 createObjectURL 方法賦予 href 屬性值,
a.download可以為下載檔案命名,最後呼叫 click 方法完成檔案下載。
還有一件事情須處理,存放檔案的主機要設定允許跨領域存取的權限
後端採用 Node.js 與 Express framework 進行開發
app.configure(function(){ app.use(function(req, res, next) { res.header('Access-Control-Allow-Origin', "*"); res.header('Access-Control-Allow-Credentials', true); res.header('Access-Control-Allow-Methods', "GET"); next(); }); });
簡單講要幫 response 設定允許跨領域存取的 Header,
'Access-Control-Allow-Origin' 設定允許的請求來源
'Access-Control-Allow-Methods'設定允許的方法,如 GET, POST 等
如果前端 xhr.setRequestHeader 有自行定義 Header 的話
那 Server 這邊也要多加 'Access-Control-Allow-Headers' 權限
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
就允許帶有 header 為 'X-Requested-With' 的請求。
但要注意的是,因為安全性的關係,XDomainRequest不支援客製化 Header
也限制 Method only GET or POST,Protocol only HTTP or HTTPS
還好IE 10開始支援 XMLHTTPRequest2
沒有留言:
張貼留言