文件下載是一個Web中非常常用的功能,不過你是做內部管理系統還是做面向公眾的互聯網公司都會遇到這個問題,對於下載一般有點實際開發經驗的都會自己解決,上周弄了一下多文件下載,業務場景就是一條數據詳細信息一個附件原來只需要一個pdf就行,現在要求添加兩張圖片,一次性的下載出來,之前沒遇到這種問題。網上找了找,有了思路,就是需要隱藏一個iframe,然后設置src,大概的原理是這樣的,之后自己開始動手擼代碼去了:
業務場景來源於公司的一個客戶管理系統,為了以后其他地方也能調用,擴展了一下方法:
(function($) {
var methods = {
_download: function(options) {
var triggerDelay = (options && options.delay) || 100;
var removeDelay = (options && options.removeDelay) || 1000;
this.each(function(index, item) {
methods._createIFrame(item, index * triggerDelay, removeDelay);
});
},
_createIFrame: function(url, triggerDelay, removeDelay) {
//動態添加iframe,設置src,然后刪除
setTimeout(function() {
var frame = $('<iframe style="display: none;" class="multi-download"></iframe>');
frame.attr('src', url);
$(document.body).after(frame);
setTimeout(function() {
frame.remove();
}, removeDelay);
}, triggerDelay);
}
};
$.fn.multiDownload = function(options) {
methods._download.apply(this, arguments);
};
})(jQuery);
上面的代碼沒什么注釋,iframe會加載src的內容,以上的程序調用很簡單,這個數組的里面的地址放的是服務器請求的地址,需要保證一點的就是服務器的原來這個地址是可以下載文件的:
var downloadUrl=['服務器請求地址1','服務器請求地址2'];
$(downloadUrl).multiDownload();
當時完成這個功能很順利,然后前天我想寫篇博客記錄一下,但我比較懶,懶的寫服務端代碼,直接把文件放在本地,去請求一下,企圖獲得同樣的結果,失敗了,先來看行代碼:
<a href="Content/keso1.zip">zip文件</a>
這個鏈接我們點擊一下直接下載了zip文件,但是如果你改成xx.jpg,xx.txt,因為瀏覽器根據 MIME TYPE(資源的媒體類型),如果請求的是后台服務器需要指定一下Content-type,處理本地的文件,沒法告訴瀏覽器某個文件的 MIME Type 的情況下,瀏覽器也會做一些默認的處理,這和個人的操作系統中給文件配置的 MIME Type 有關。本人電腦是Window,如果需要看具體Content-type,詳細地址如下:

所以通常圖片和文本有的時候就直接打開顯示,而rar,zip文件瀏覽器不識別Content-type當做文件下載;
為了能直接下載這個圖片,找到了Html5中有一個download屬性,如果你將一個a標簽加上一個download屬性,jpg文件直接當做文件下載了,href就是圖片地址,瀏覽器兼容沒有測試,畢竟5來日方長:
<a download="keso.jpg" href="keso.jpg">Html5下載</a>
這個時候就可以動手該原來的代碼,如果點擊的時候直接這個方法是可以自動下載文件的,單文件下載之后就可以進行多文件下載啦:
function downloadHtml5(url){
var aLink = document.createElement('a');
, evt = document.createEvent("HTMLEvents");
evt.initEvent("click");
aLink.download ="";
aLink.href =url;
aLink.dispatchEvent(evt);
}
修改擴展方法:
(function($) {
var methods = {
_download: function(options) {
var triggerDelay = (options && options.delay) || 100;
var removeDelay = (options && options.removeDelay) || 1000;
if (options.source === "server") {
this.each(function(index, item) {
methods._createIFrame(item, index * triggerDelay, removeDelay);
});
};
if (options.source === "local") {
this.each(function(index, item) {
methods._createLink(item, index * triggerDelay, removeDelay);
});
};
},
_createIFrame: function(url, triggerDelay, removeDelay) {
//動態添加iframe,設置src,然后刪除
setTimeout(function() {
var frame = $('<iframe style="display: none;" class="multi-download"></iframe>');
frame.attr('src', url);
$(document.body).after(frame);
setTimeout(function() {
frame.remove();
}, removeDelay);
}, triggerDelay);
},
//download屬性設置
_createLink: function(url, triggerDelay, removeDelay) {
var aLink = document.createElement("a"),
evt = document.createEvent("HTMLEvents");
evt.initEvent("click");
//需要添加屬性,不需要設置文件名,個人測試就是原文件名,設為空沒有問題,具體情況具體分析
aLink.download = "";
aLink.href = url;
aLink.dispatchEvent(evt);
}
};
$.fn.multiDownload = function(options) {
methods._download.apply(this, arguments);
};
})(jQuery);
最終代碼調用,六個文件都可以下載:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JQuery文件下載</title>
<script type="text/javascript" src="jquery-1.11.1.js"></script>
<script type="text/javascript" src="jquery.multidownload-FlyElephant.js"></script>
<script type="text/javascript">
$(function() {
$("#download").click(function() {
var downloadUrl = ['Content/keso1.jpg','Content/keso2.jpg','Content/keso1.txt','Content/keso2.txt','Content/keso1.zip','Content/keso2.zip'];
$(downloadUrl).multiDownload({"source":"local"});
});
});
</script>
</head>
<body>
<a id='download' href="#">下載</a>
<a download="keso.jpg" href="keso.jpg">Html5下載</a>
<a href="Content/keso1.zip">zip文件</a>
<div>
<Image src="keso.jpg" />
<Image src="FlyElephant.jpg" />
</div>
</body>
</html>
個人非專業前端,難免有遺漏或不到位的地方,如有不當請多多指正,多謝~
參考資料: 在瀏覽器端用JS創建和下載文件 AlloyTeam
