前端如何通過連結去下載img圖片

紫菜薹同學發表於2019-04-11

很多專案中都有下載一些圖片檔案的需求,常用的方式是通過a標籤實現:

<a href="download.jpg"></a>
複製程式碼

但是你會在使用時發現點選該連結後並不是下載對應的圖片,而是在瀏覽器中開啟了對應的圖片,這並不是我們想要的。

應為瀏覽器判斷是否下載一般會根據檔案返回的頭資訊進行判斷,如果給返回了對應的頭資訊則會進行下載:

header('Content-type: image/jpeg'); 
header("Content-Disposition: attachment; filename='download.jpg'"); 
複製程式碼

很好,但是如果這樣還需要後端人員的配合,我們有沒有其他的方式呢?有,那就是使用download屬性:

<a href="download.jpg" download>下載</a>
複製程式碼

這樣就可以直接呼叫瀏覽器的下載功能,而且還可以通過傳參給download來實現檔案的重新命名功能:

<a href="download.jpg" download="othername.jpg">下載</a>
複製程式碼

download屬性的相容性如下:

caniuse.com/download/em…

但是這個方案依然有他的問題:

chrome 69.0.3497.92 中已經嚴格遵循同源策略的限制,如果載入了非同源的內容,download 屬性將失效,等效導航功能。

現在很多專案已經是前後端分離,經常遇到跨域的問題,但是在跨域的情況下download屬性完全沒有作用,那麼應該如何解決。

基本的思路就是讓跨域變成不是跨域。


一種思路就是通過反向代理進行處理,來解決跨域問題:

1.將原先訪問圖片雲服務的資源改為訪問網站圖片資源,例如:

  <a href="http://prod.upaiyun.com/images/xxx.jpg" download="xxx.jpg">download</a>
  改為:
  <a href="http://www.mysite.com/images/xxx.jpg" download="xxx.jpg">download</a>
複製程式碼

2.配置nginx反向代理

  location /images {
    proxy_redirect    off;
    proxy_pass https://prod.upaiyun.com;
  }
複製程式碼

另一種方式就是,建立一個非跨域的資料來源:

1.下載原資料檔案,這裡可以使用img標籤或者通過ajax,fetch進行下載

   function download(url, name) {
        name = name || url
        // fetch抓取圖片資料
        fetch(url).then(response=> {
            if( response.status == 200 )
                // 返回的.blob()為promise,然後生成了blob物件,此方法獲得的blob物件包含了資料型別,十分方便
                return response.blob()
            throw new Error(`status: ${response.status}.`)
        }).then(blob=> {
            // 獲取到blob物件
            downloadFile(name, blob)
        }).catch(error=> {
            console.log("failed. cause:", error)
        })
    }
複製程式碼

2.通過URL.createObjectURL給a標籤設定資料來源

function downloadFile(fileName, blob) {
       const anchor = document.getElementById("a")
       // 建立指向blob物件地址
       const src = URL.createObjectURL(blob)
       anchor.download = fileName
       anchor.href = src
}
複製程式碼

這樣就可以實現在跨域情況下的圖片資源的下載。

當然還有一下其他類似的方案如使用FileReaderreadAsDataURL來生成資料,或使用CanvastoDataUrl都可以達到一樣的效果。

相關文章