說一說前端文件壓縮

基於JSZip的前端文件壓縮

1. 簡介:

這段時間,項目須要作一個這樣的功能:客戶端在上傳文件的時候(具體文件類型),須要對文件進行壓縮再上傳以節省帶寬和服務器端資源,完成這個功能,咱們選擇了GitHub上的JSZip,它是一個客戶端插件,能夠提供客戶端壓縮功能,做者給出了API,可是實際使用過程當中仍是有不少問題,下面是實際過程當中遇到的各種問題,直至最終完成整個文件壓縮再上傳至後臺。html

2.項目相關組件與環境:

前端node.js + webpack 做先後臺分離,後端java前端

3. 具體實現

主要js代碼:java

var JSZip = require('jszip');
const components = require('components');

$('#confirmBtn').on('click', async function() {
  // 綁定上傳的確認按鈕,獲取到obj等模型文件,並壓縮
  let zip = new JSZip();//聲明並建立JSZip對象
  var fileBox = $('#fileUploadInput'); //從頁面獲取到須要上傳的文件列表,固然html是一個多文件上傳
  var fileList = fileBox[0].files;
  var objName = 'example'; // 這裏定義一個壓縮文件的名字,以供後臺使用,固然也能夠動態獲取
  //  var flag = false;
  for (const fileObject of fileList) {
    zip = await zipFileAsync(zip, fileObject); //這是設置異步上傳,await關鍵字使得後面的zipFileAsync方法執行結束後纔將對象返回給zip變量
  }
  sendFileAsync(zip, objName);
  console.log(zip);
  return false; // 設置return false防止表單提交
});

這部分代碼就是異步壓縮的核心,以及如何調用的下面的異步壓縮算法,上面須要Async與await關鍵字缺一不可,一開始也嘗試過使用同步壓縮的方式,可是會出現壓縮尚未所有完成,就已經開始提交文件的現象,特別感謝lrh3321的指導,才完整的實現了這個功能。node


由於異步壓縮的時候咱們上傳的文件的數量不定,因此上面須要使用await關鍵字來修飾壓縮過程。而下面的壓縮過程的實現,最終返回一個promise對象,當壓縮過程已完成後,完整的生成的文件存於其中。webpack

/**
 * 異步壓縮文件
 * @param zip file
 */
function zipFileAsync(zip, file) {
  const promise = new Promise((resolve) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onloadend = function(e) {
      var result = reader.result;
      //  讀完轉一下格式
      result = convertBase64UrlToBlob(result);
      console.log(zip);
      console.log(file.name);
      console.log(file.size);
      // resolve 方法保證異步壓縮完成後才返回promise
      resolve(
        zip.file(file.name, result, {
          type: 'blob',
        }));
    };
  });
  return promise;
}

這裏的demo請查看JSZip給的例子git

/**
 * 異步發送文件
 * @param zip file
 */
function sendFileAsync(zip, objName) {
  zip.generateAsync({
    type: 'blob',
    compression: 'DEFLATE', //  force a compression for this file
    compressionOptions: { //  使用壓縮等級,1-9級,1級壓縮比最低,9級壓縮比最高
      level: 6,
    },
  }).then(
      function(content) {
        var formData = new FormData();
        formData.append('Blobfile', content); // 獲取上文中壓縮的內容,並放入formdata
        formData.append('objName', objName); // 將objName一塊兒放入formdata
        progressBar('Model/UploadModel', formData, content.size); 
      }
  );
  return false;
}
/**
 * 將以base64的圖片url數據轉換爲Blob
 * @param urlData
 * 用url方式表示的base64圖片數據
 */

http讀取圖片的時候會已base64編碼形式對到服務器,若是不進行從新編碼,則沒法在圖片查看器中查看圖片github

function convertBase64UrlToBlob(urlData) {
  var bytes = window.atob(urlData.split(',')[1]);
  //  處理異常,將ascii碼小於0的轉換爲大於0
  var ab = new ArrayBuffer(bytes.length);
  var ia = new Uint8Array(ab);
  for (var i = 0; i < bytes.length; i++) {
    ia[i] = bytes.charCodeAt(i);
  }
  return new Blob([ab], {type: 'image/jpg'});
}
相關文章
相關標籤/搜索