前端實現點選下載圖片

LFE發表於2018-08-23

為什麼要寫這個方法呢

     這幾天接到一個需求,頁面列表中有很多按鈕,點選按鈕可以下載對應的圖片。平時自己上網下載圖片都是滑鼠右鍵另存為的,但是這裡觸發儲存的動作是點選下載按鈕。只能硬著頭皮去網上找答案,原來方法是這麼的多:通過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,和一個字串格式的圖片路徑

參考

知乎專欄-web前端開發

相關文章