使用h5 標籤 href='url' download 下載踩過的坑

用戶點擊下載多媒體文件(圖片/視頻等),最簡單的方式:

<a href='url' download="filename.ext">下載</a>

如果url指向同源資源,是正常的。

如果url指向第三方資源,download會失效,表現和不使用download時一致——瀏覽器能打開的文件,瀏覽器會直接打開,不能打開的文件,會直接下載。瀏覽器打開的文件,可以手動下載。

解決方案一:將文件打包爲.zip/.rar等瀏覽器不能打開的文件下載。

解決方案二:通過後端轉發,後端請求第三方資源,返回給前端,前端使用file-saver等工具保存文件。

 

如果url指向的第三方資源配置了CORS,download依然無效,但可以通過xhr請求獲取文件,然後下載到本地。

/**
 * 用FileSave保存文件
 * @param url
 */
export function downloadUrlFile(url) {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.responseType = 'blob';
  xhr.setRequestHeader('Authorization', 'Basic a2VybWl0Omtlcm1pdA==');
  xhr.onload = () => {
    if (xhr.status === 200) {
      // 獲取圖片blob數據並保存
      saveAs(xhr.response, 'abc.jpg');
    }
  };

  xhr.send();
}

/**
 * URL方式保存文件到本地
 * @param name 文件名
 * @param data 文件的數據
 */
function save(name, data) {
	var urlObject = window.URL || window.webkitURL || window;
	var export_blob = new Blob([data]);
	var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a')
	save_link.href = urlObject.createObjectURL(export_blob);
	save_link.download = name;
	_fakeClick(save_link);
}

 

第三方跨域多媒體資源無法直接下載。很奇怪,瀏覽器不能打開的文件可以下載,瀏覽器能打開的文件不能下載,這個限制似乎沒有多大意義。

不依靠後端,有兩個可能破解這個限制的思路。

1、window.open(url),再向新窗口寫入一個<a href='url' downlad></a>,觸發點擊。

驗證結果:這種向別人的網頁中嵌入自己內容的方式,極大影響瀏覽器的安全,無法實現。

2、<img src='url'  οnlοad='onload'>, onload的回調中,將img 繪入 canvas,canvas.toDataUrl(),然後保存。

MDN給出的例子        使用download保存畫布爲png

驗證結果:canvas.drawImage(img,0,0)後,canvas被跨域資源污染,canvas.toDataUrl()調用報錯。

/**
   * 下載url圖片
   * @param imageUrl
   */
  const downloadUrl = (imageUrl) => {
    const downloadCanvas = $('#download-canvas')[0];
    const img = new Image();
    img.onload = () => {
      const ctx = downloadCanvas.getContext('2d');
      ctx.drawImage(img, 0, 0);
      const imageDataUrl = downloadCanvas.toDataURL('image/jpeg'); 
      // Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
      saveAs(imageDataUrl, '附件');
    };
    img.src = imageUrl;
  };

結論:

瀏覽器已經限制死跨域下載多媒體文件的各種方式。

最正規的辦法還是讓後端做一次轉發。請求後端,後端向第三方請求文件,返回給前端,前端保存文件。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章