前面一直做過下載的功能。就是后台將文件流寫入response里面,然后就好了。前台會自動彈出下載提示等。
今天打算做一個ajax下載。想當然的結果死活瀏覽器沒反應。我擦。
然后瀏覽器調試,發現response返回過來的是一串類似亂碼的文本而不是二進制文件流。定位原因在這里。
之后繼續百度,如何實現ajax異步下載。回答是這樣的:
那就是請求方式有問題,文件下載的請求是不能寫在ajax里面的!
原因:因為response原因,一般請求瀏覽器是會處理服務器輸出的response,例如生成png、文件下載等,然而ajax請求只是個“字符型”的請求,即請求的內容是以文本類型存放的。文件的下載是以二進制形式進行的,雖然可以讀取到返回的response,但只是讀取而已,是無法執行的,說白點就是js無法調用到瀏覽器的下載處理機制和程序。
然后繼續百度,我有點不信邪。找到這篇文章:http://www.cnblogs.com/cdemo/p/5225848.html
原來ajax並非只能獲取文本而不能獲取二進制流,只是jquery封裝的ajax的問題。
抱怨:jquery做了這么久了 一個ajax方法還停留在幾年前的xmlhttprequest 1的版本中,驚人的不支持流文件!!! 我這還怎么大肆推行我的前后台完全隔離思想~~。算了不抱怨了,果然是不能靠別人,只能自己寫了。 樓主依稀記得 xmlhttprequest 2 標准中支持流文件的,並且應該使用 xhr.response作為返回 而不是responseText。
於是使用原生的ajax獲取流文件:
var url = serverUrlBase + "/server/images/" + mapid + "/files/png"; var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = "blob"; xhr.setRequestHeader("client_type", "DESKTOP_WEB"); xhr.setRequestHeader("desktop_web_access_key", _desktop_web_access_key); xhr.onload = function() { if (this.status == 200) { } } xhr.send();
獲取到了文件,然后原貼中需要的操作是展示,使用blob對象。
這樣應該可行,但是怎么處理請求的數據呢? ???? 這個問題。 對了 html5新特性里面是不是 提到一個 Blob對象來着。試試看。
通過查閱相關blob資料,查閱 4.6.9 The response
attribute 得知 返回類型應該使用
於是原貼中剩下的是建造img標簽,賦值各個屬性,結果得到了。
然后我懵逼了,我需要的是下載啊。有點急着要結果,所以我先放開了這種思路。
我記得搜索得到別人的做法是使用一個iframe,得到不刷新原來頁面下載的效果,也就是它使用直接其它層直接訪問的方式模擬了ajax。發現,真簡單:
參考這篇文章:http://www.jb51.net/article/47294.htm
代碼:
<script> function download() { //下載文件的地址 var url="http://music.baidu.com/data/music/file?link=http://zhangmenshiting.baidu.com/data2/music/13618994/13618995183600128.mp3?xcode=48d4a720fcd9a974586066d0145f7207"; document.getElementById("ifile").src=url; } </script> <a href="#" onclick="download()">download</a> <iframe id="ifile" style="display:none"></iframe>
區別只是將我的鏈接替換進去了。
效果達到了,但還有點不死心,輕易得到的東西總是不會珍惜。我還是想看看我的ajax下載。我想啊,我都能在頁面得到元素了,為什么我不能下載呢?
於是百度搜索前端js下載
剛好發現了一篇文章:http://blog.csdn.net/greatbody/article/details/70207232
思路:
我已經做好了一半了。剩下下載就是了。於是我模擬它的方法將自己的代碼改寫了一下。
<script type="text/javascript"> function f() { var url = "/servlet/example"; // document.getElementById("ifile").src=url; var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = "blob"; xhr.onload = function() { if (this.status == 200) { var blob = this.response; downloadFile(fileNameFromHeader(xhr.getResponseHeader("Content-Disposition")), xhr.response); } } xhr.send(); } function fileNameFromHeader(disposition) { var result = null; if (disposition && /filename=.*/ig.test(disposition)) { result = disposition.match(/filename=.*/ig); return decodeURI(result[0].split("=")[1]); } return "undefine_file"; } function downloadFile(fileName, content) { var aLink = document.createElement('a'); var blob = new Blob([content]); var evt = document.createEvent("MouseEvents"); evt.initEvent("click", true, true); if (fileName) { aLink.download = fileName; } aLink.target = "_blank"; aLink.href = URL.createObjectURL(blob); aLink.dispatchEvent(evt); } </script>
注意它前端下載的代碼:
function downloadFile(fileName, content) { var aLink = document.createElement('a'); var blob = new Blob([content]); var evt = document.createEvent("MouseEvents"); evt.initEvent("click", true, true); if (fileName) { aLink.download = fileName; } aLink.target = "_blank"; aLink.href = URL.createObjectURL(blob); aLink.dispatchEvent(evt); }
創建一個a連接,a鏈接的地址為要訪問的對象,這里是我們的Blon對象,然后js點擊,在新窗口。