前端實現批量打包下載文件


需求說明:

  后端接口返回附件列表(含URL),這些附件存在阿里雲OSS上。一期需求是實現對列出的附件進行點擊下載,也就是每次只下載點擊的附件(PDF | 圖片),使用一段時間后制定二期需求時,增加批量下載功能,需要打包在一起。附言:本文所寫都是純前端實現,后端接口只需要返回路徑即可。

單獨下載圖片:

  直接使用<a>標簽,會存在這樣的問題:同源鏈接點擊后直接在瀏覽器打開,通過在<a>標簽內指定download屬性可以避免,但是非同源鏈接卻不行。所以通過Canvas + JS方式實現點擊圖片直接下載,這里要解決這么幾個問題:1、非同源及跨域問題;2、Canvas圖片下載限制問題。同源問題很好解決,只需要一行代碼:

image.setAttribute('crossOrigin', 'anonymous')

為了解決Canvas圖片像素大小的限制,轉為blod流數據,下面附上代碼:

  /**
   * @param {Number} imgsrc 圖片路徑
   * @param {Number} name 自定義圖片名稱
   * 直接使用canvas下載有圖片像素大小的限制,所以轉成blod流下載
   **/
  downloadIamge (imgsrc, name) { // 下載圖片地址和圖片名
    let image = new Image()
    // 解決跨域 Canvas 污染問題
    image.setAttribute('crossOrigin', 'anonymous')
    let fun = this.dataURLtoBlob
    image.onload = function () {
      let canvas = document.createElement('canvas') // 創建Canvas
      canvas.width = image.width
      canvas.height = image.height
      let context = canvas.getContext('2d')
      context.drawImage(image, 0, 0, image.width, image.height) // Canvas畫圖
      let url = canvas.toDataURL({format: 'png', multiplier: 4}) // 通過toDataURL()方法將圖像轉為url
      var blob = fun(url)
      var objurl = URL.createObjectURL(blob) // 轉成blod
      let a = document.createElement('a') // 生成一個a元素
      let event = new MouseEvent('click') // 創建一個單擊事件
      a.download = name || "'photo" // 設置圖片名稱
      a.href = objurl // 將生成的URL設置為a.href屬性
      a.dispatchEvent(event) // 觸發a的單擊事件
    }
    image.src = imgsrc + '?=' + Math.random() // 加入隨機數 解決跨域不能下載問題
  },

  /**
   * @param {string} dataurl 圖像地址
   * 轉blod流
   */
  dataURLtoBlob (dataurl) {
    let arr = dataurl.split(',')
    let mime = arr[0].match(/:(.*?);/)[1]
    let bstr = atob(arr[1])
    let n = bstr.length
    let u8arr = new Uint8Array(n)
    while (n--) {
      u8arr[n] = bstr.charCodeAt(n)
    }
    return new Blob([u8arr], {type: mime})
  }

在實現的時候,如果這樣指定image的src屬性:

image.src = imgsrc 

在運行之后,發現並沒有解決非同源圖片直接打開的問題,所以在下載地址后加了隨機數

image.src = imgsrc + '?=' + Math.random()

打包批量下載:

  這里使用了其他的包:JSZip(用於文件打包)和 file-saver(用於下載),因為是在Vue項目中使用,直接在項目中下載

npm install jszip
npm install file-saver

 在需要使用的文件中引入:

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

下載主方法代碼如下:

  // <button @click="down">批量下載</button>
    async down() {
      try {
        let zip = new JSZip();
        for (let i = 0; i < this.arr.length; i++) {
          let lst = this.arr[i].split(".");
          let fileType = lst[lst.length - 1];
          if (fileType.toLocaleUpperCase() === "PDF") {
            await this.getFile(this.arr[i]).then(pdf => {
              zip.file("HelloPDF.pdf", pdf, { binary: true });
            });
          } else {
            await this.getBase64Image(this.arr[i]).then(res => {
              zip.file("HelloIMG" + i + "." + fileType, res, { base64: true });
            });
          }
        }
        this.downImg(zip);
      } catch (err) {
        console.log("err", err);
      }
    },

這里使用了async/await來進行文件異步操作,確保zip填充操作執行完之后,才執行zip的下載。

downImg(zip) {
  zip
    .generateAsync({
      type: "blob"
    })
    .then(content => {
      let fileName = "批量下載.zip";
      FileSaver.saveAs(content, fileName);
    });
},
//****傳入圖片鏈接,返回base64數據
getBase64Image(url) {
  return new Promise((resolve, reject) => {
    var base64 = "";
    var img = new Image();
    img.setAttribute("crossOrigin", "Anonymous");
    img.onload = () => {
      base64 = this.image2Base64(img);
      resolve(base64.split(",")[1]);
    };
    img.onerror = () => reject("加載失敗");
  // 這里可能會有跨域失敗的問題,解決方案同上,url + 隨機數 img.src
= url; }); }, image2Base64(img) { var canvas = document.createElement("canvas"); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, img.width, img.height); var dataURL = canvas.toDataURL("image/png"); return dataURL; }, //****傳入文件鏈接,返回arraybuffer數據 getFile(url) { return new Promise((resolve, reject) => {
  // 這里的$http是Vue里的axios
this.$http({ method: "get", url, responseType: "arraybuffer" }) .then(data => { resolve(data.data); }) .catch(error => { reject("PDF加載失敗:" + error); }); }); },

 

以上,實現方式記錄。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM