為什麼要寫這個方法呢
這幾天接到一個需求,頁面列表中有很多按鈕,點選按鈕可以下載對應的圖片。平時自己上網下載圖片都是滑鼠右鍵另存為的,但是這裡觸發儲存的動作是點選下載按鈕。只能硬著頭皮去網上找答案,原來方法是這麼的多:通過a標籤下載,通過使用canvas下載,通過使用blob下載,通過使用iframe下載等等。但由於考慮到使用純前端技術實現和相容性問題,最終自己總結出兩個比較靠譜的方法,並封裝成一個工具類,在此分享出來,如有錯誤還請指出,希望能相互學習。
方法總結
- 方法一:使用a標籤的download屬性。
如:
<a href="1.jpg" download="1.jpg">下載圖片</a>
複製程式碼
- 方法二:使用iframe標籤,其src指向圖片地址,另外呼叫document.execCommand("SaveAs")方法。
但要注意的是在非Trident核心瀏覽器(即非IE瀏覽器)下並不支援a標籤的下載方法,所以本工具類目的是對其進行封裝能夠適應大部分的圖片下載
程式碼實現
function DownloadImg() {
this.frame = null; //
this.isIE = !!window.ActiveXObject || ("ActiveXObject" in window);
}
/**
*@param clickId a標籤的id值
*@param imgUrl 要下載的圖片的路徑
*/
DownloadImg.prototype.init = function(clickId, imgUrl) {
var oA = document.getElementById(clickId),
that = this;
/*檢測是否為同源圖片*/
var imgHost, localHost = location.host,
doubleIndex = imgUrl.indexOf('//');
if (doubleIndex != -1) {
imgHost = imgUrl.substring(doubleIndex + 2, imgUrl.indexOf(doubleIndex + 2));
if (imgHost != localHost) { //如果圖片非同源
oA.href = imgUrl;
return;
}
}
/*檢測是否為同源圖片end*/
if (that.isIE) { //如果是IE瀏覽器,使用方法二
oA.onclick = function() {
that.createIframe(imgUrl);
}
} else { //如果是非IE瀏覽器,使用方法一
oA.download = imgUrl.substring(imgUrl.lastIndexOf('/') + 1);
oA.href = imgUrl;
}
}
DownloadImg.prototype.createIframe = function(imgUrl) {
var that = this;
//如果隱藏的iframe不存在則建立
if (!this.frame) {
var oBody = document.getElementsByTagName('body')[0],
frame = document.createElement('iframe');
frame.style.display = 'none';
frame.name = 'downloadIframe';//在IE7下設定好的name屬性會變成submitName,用setAttribute設定也是同樣效果,待解決
frame.width = 0;
frame.height = 0;
this.frame = frame;
// this.frame.onload = this.downloadImg();//這種方式繫結會有問題,待解決
this.addEvent(this.frame, 'load', function() { //給iframe繫結一個load方法,load完成便會觸發下載方法
that.downloadImg();
})
oBody.appendChild(this.frame); //將建立的iframe新增到body中
}
if (this.frame.src != imgUrl) { //如果本次要下載的圖片路徑不等於上一次下載的圖片路徑,那麼對iframe進行重新賦值,那麼又將會觸發load事件,從而間接的觸發下載事件
this.frame.src = imgUrl;
} else { //如果本次要下載的圖片路徑等於上一次下載的圖片路徑,直接呼叫下載圖片方法
this.downloadImg();
}
}
DownloadImg.prototype.downloadImg = function() {
if (this.frame.src != '' && this.frame.src != 'about:blank') { //如果iframe的src路徑存在那麼呼叫下載瀏覽器的儲存方法
window.frames["downloadIframe"].document.execCommand("SaveAs");
}
}
DownloadImg.prototype.addEvent = function(el, eventType, handler) { //事件相容
if (el.attachEvent) {
el.attachEvent('on' + eventType, handler);
} else if (el.addEventListener) {
el.addEventListener(eventType, handler, false);
} else {
el['on' + eventType] = handler;
}
}
複製程式碼
工具類的使用
//例項化這個工具類
var downloadImg = new DownloadImg();
//傳入a標籤的id,和要分別下載的圖片地址進行初始化
downloadImg.init('download', 'https://gss0.bdstatic.com/5bVWsj_p_tVS5dKfpU_Y_D3/res/r/image/2017-09-27/297f5edb1e984613083a2d3cc0c5bb36.png');
downloadImg.init('download1', './imgs/1.png');
複製程式碼
注意的問題
-
這兩種方法實現點選下載的前提是要下載的圖片是同源的,那麼意味著其他網站的圖片是不能實現點選下載的。如果使用本方法,在非IE瀏覽器中會直接跳轉到該圖片的預覽地址,而在IE瀏覽器下則直接報錯,因此該工具對此進行了優雅降級,如果是非同源圖片,直接進行跳轉預覽,讓使用者自己滑鼠右鍵另存為去吧~~
-
這裡點選下載的實現都是由a標籤觸發的,因此在頁面上的按鈕也需要使用該標籤來書寫
-
這裡沒有做過多的優化處理和引數檢測,初始化的時候只能傳入一個id,和一個字串格式的圖片路徑