1. 程式人生 > 其它 >前端實現檔案下載(支援打包下載)

前端實現檔案下載(支援打包下載)

最近做專案時有遇到讓前端實現檔案下載並且支援批量打包下載的需求,記錄一下實現方案,如有錯誤之處或有更好的方法,還望各位不吝指正!

一、首先想到的方案是通過a標籤指定href和download屬性

實踐中發現,這種方式的侷限是download屬性受同源策略影響,當資源跨域時,download屬性失效。結果變成了預覽而不是下載,如果第三方配置了CORS則能下載但下載時不能重新命名檔案。

二、適用於圖片下載:將url轉成base64後再由a標籤下載

imgToBase64(url, cb) {
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    var img = new Image();
    img.crossOrigin = 'Anonymous';
    img.onload = function () {
      canvas.width = img.width;
      canvas.height = img.height;
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
      const result = canvas.toDataURL();
      cb(result);
      canvas = null;
    };
    img.src = url;
  }

// 建立a標籤下載
downOption(fileUrl, fileName) {
    let link = document.createElement('a');
    link.href = fileUrl;
    link.target = '_blank';
    link.rel = 'noopener norefferrer';
    link.download = fileName;
    link.style.display = 'none';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  }

// downloadFileUrl: 'http://XXXXX.jpg'
downLoadImg(){
  this.imgToBase64(downloadFileUrl).then(dataURL => {
        this.downOption(dataURL, '指定檔名字')
  })
}

三、通用的檔案下載(適合圖片/視訊/PDF等等)

以axios為例,或者用xhr也可以

downloadFile({ url, name }) {
    axios({
      url: url,
      method: 'get',
      responseType: 'blob'
    }).then(res => {
      let blob = new Blob([res.data], { type: res.data.type });
      let newUrl = URL.createObjectURL(blob);
      this.downOption(newUrl, name);
    });
  }

四、打包下載(以打包圖片下載為例)

需要依賴第三方庫

import JSZip from 'jszip';
import FileSaver from 'file-saver'; 

batchDownload(){
  const zip = new JSZip();
        imageList.forEach(imgItem => { // imageList儲存要下載的圖片陣列
          const fileType = imgItem.url.slice(imgItem.url.lastIndexOf('.'));
          this.imgToBase64(imgItem.url, (dataURL) => {
            const formatUrl = dataURL.split(',')[1];
            zip.file(imgItem.name + fileType, formatUrl, { base64: true }); // 指定檔名和字尾、base64
            if (Object.keys(zip.files).length === imageList.length) {
              zip.generateAsync({ type: 'blob' }).then((content) => {
                FileSaver.saveAs(content, '素材圖片.zip'); // 用saveAs也可以
              });
            }
          });
        });
}