前端圖片壓縮與 zip 壓縮


  在項目中,為了節約網絡消耗,需要將文件進行壓縮后上傳服務端。

  最開始考慮的是將文件壓縮為 zip ,由服務端返回后前端 zip 再進行解壓。但 zip 對小文件、圖片、視頻的壓縮效果很差。所以需要多種壓縮方式配合使用。

  圖像采用 canvas 有損壓縮:

 utils.dealImage = (base64, rate) => {
    return new Promise((resolve, reject) => {
      try {
        let newImage = new Image();
        let quality = rate || rate > 1 || rate <= 0 ? rate : 0.6; //壓縮系數0-1之間
        // newImage.setAttribute("crossOrigin", 'Anonymous'); //url為外域時需要
        let imgWidth, imgHeight;
        newImage.onload = function () {
          imgWidth = this.width;
          imgHeight = this.height;
          let canvas = document.createElement("canvas");
          let ctx = canvas.getContext("2d");
          canvas.width = imgWidth;
          canvas.height = imgHeight;
          ctx.clearRect(0, 0, canvas.width, canvas.height);
          ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
          let base64 = canvas.toDataURL("image/jpeg", quality); //壓縮語句
          resolve(base64);
        }
        newImage.src = base64;
      } catch (err) {
        reject(err);
      }
    })
  }

  其余文件采用 zip 方式無損壓縮,這里使用的是 jszip :

// 文件 base64 壓縮為 zip
utils.zip = (base64, fileName) => {
    let inputBlob = utils.dataURItoBlob(base64);
    let JSZip = require("jszip");
    let zip = new JSZip();
    zip.file(fileName, inputBlob, {
      type: "blob"
    });
    // return a promise
    return zip.generateAsync({
      type: "blob",
      compression: "DEFLATE", // force a compression for this file
      compressionOptions: {
        level: 9,
      },
    });
  }

  //blob to base64
  utils.blobToDataURI = (blob) => {
    return new Promise((resolve, reject) => {
      try {
        var reader = new FileReader();
        reader.readAsDataURL(blob);
        reader.onload = function (e) {
          resolve(e.target.result);
        };
      } catch (err) {
        reject(err);
      }
    });
  }

  // base64 to blob
  utils.dataURItoBlob = (dataURI) => {
    let mimeString = dataURI.split(",")[0].split(":")[1].split(";")[0]; // mime類型
    let byteString = atob(dataURI.split(",")[1]); //base64 解碼
    let arrayBuffer = new ArrayBuffer(byteString.length); //創建緩沖數組
    let intArray = new Uint8Array(arrayBuffer); //創建視圖
    for (let i = 0; i < byteString.length; i++) {
      intArray[i] = byteString.charCodeAt(i);
    }
    return new Blob([intArray], {
      type: mimeString,
    });
  }

  對於視頻和小文件,暫時沒有找到合適的壓縮方式。且因為 zip 的壓縮率不穩定,對於壓縮后文件還需要進行二次判斷大小才可上傳服務端,目前測試綜合壓縮率在 60% 左右。

  另,因項目中,源文件也可能被客戶下載,因此采用了 zip 的壓縮方式方便用戶解壓。僅就壓縮率看,snappy 與 7z 也是很好的選擇。


免責聲明!

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



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