前端打包壓縮下載


JSZip和FileSaver.js

本節會簡單的介紹一下JSZip和FileSaver.js的API和用法。

安裝

npm install jszip file-saver

  

 

JSZip

JSZip是一個用於創建、讀取和編輯.zip文件的javascript庫,並且擁有有友好而簡單的API。

一個簡單的例子

首先我們來實現一個簡單的例子,來感受一下這個十分好用的工具

import React , { useState } from 'react';
import JSZip from 'jszip';
import FileSaver from 'file-saver'; 


const MyButton = () => {

    const downloadFile = () => {
        const zip = new JSZip();
        zip.file("Hello.txt", "Hello World\n");
        zip.generateAsync({type:"blob"})
        .then((content) => { 
            FileSaver(content, "example.zip");
        });
    }

    return (
        <div>
            <button onClick={() => {
                downloadFile()
            }}>下載</button>
        </div>
    )
} 

export default MyButton

 

download() {
	const zip = new JSZip();   // 實例化zip
    const img = zip.folder("qrCode");   // zip包內的文件夾名字
    this.listOfData.forEach((item) => {  // listOfData是含有圖片的數據數組
        const basePic = item.url.replace(/^data:image\/(png|jpg);base64,/, "");  // 生成base64圖片數據
        img.file(item.name + '的二維碼.png', basePic, { base64: true });  // 將圖片文件加入到zip包內
    })
    zip.generateAsync({ type: "blob" })   // zip下載
      .then(function (content) {
        // see FileSaver.js
        saveAs(content, "二維碼.zip");  // zip下載后的名字
      });
}

  

import JSZip from 'jszip'
import FileSaver from 'file-saver'
getFile = (url) => {
    return new Promise(resolve => {
        const xhr = new XMLHttpRequest();
        // 避免 200 from disk cache
        url = url + `?r=${Math.random()}`;
        xhr.open('GET', url, true);
        xhr.responseType = 'blob';
        xhr.onload = () => {
            if (xhr.status === 200) {
              resolve(xhr.response);
            } else {
              resolve(); // 避免圖片下載失敗,導致批量導出失敗
            }
        };
        xhr.send();
    });
}
// 批量下載
handleBatchDownload = async (selectImgList, idArray) => {
    const data = selectImgList;
    const zip = new JSZip();
    const cache = {};
    const promises = [];
    await data.forEach((item, index) => {
      const promise = this.getFile(item).then((fileData) => {
        // 下載文件
        const arrName = item.split('/');
        let fileName = arrName[arrName.length - 1]; // 獲取文件名
        // 轉碼文件名, 上傳的文件用decodeURIComponent轉漢字
        const endIndex = fileName.lastIndexOf('.');
        const format = fileName.slice(endIndex);
        const startName = fileName.slice(0, endIndex);
        const newFileName = decodeURIComponent(startName) + format;
        zip.file(newFileName, fileData as any, {
          binary: true
        }); // 逐個添加文件
        cache[newFileName] = fileData;
      });
      promises.push(promise);
    });
    Promise.all(promises).then(() => {
      zip
        .generateAsync({
          type: 'blob'
        })
        .then(async (content) => {
          // 生成二進制流;利用file-saver保存文件
          FileSaver.saveAs(
            content, 
            `壓縮文件.zip`
          );
        });
    });
  };  

  

點擊下載按鈕,我們就可以得到一個名為example.zip的壓縮文件,打開壓縮文件,里面也會有一個名為Hello.txt的文件.

API

簡單介紹一下幾個API。

創建JSZip實例:

const zip = new JSZip();

  

 

創建文件:

zip.file("hello.txt", "Hello World\n");

 

創建文件夾:

zip.folder("file")

  

同時創建文件夾和文件:

zip.file("file/hello.txt", "Hello World\n");
// 等同於
zip.folder("file").file("hello.txt", "Hello World\n");

 

生成一個壓縮文件:

我們可以通過.generateAsync(options) 或者 .generateNodeStream(options) 來生成一個壓縮文件:

let promise = null;
if (JSZip.support.uint8array) {
  promise = zip.generateAsync({type : "uint8array"});
} else {
  promise = zip.generateAsync({type : "string"});
}

  

詳細API點擊官方文檔

FileSaver.js

在前面的這個例子中我們運用了JSZip外還使用了FileSaver.js這個庫。FileSaver.js是在客戶端保存文件的解決方案,非常適合在客戶端生成文件。

在上一節的例子中,我們就是通過FileSaver.js把我們生成的.zip文件保存了下來。

語法

FileSaver saveAs(Blob/File/Url, optional DOMString filename, optional Object { autoBom })

  

 

例子

import FileSaver from 'file-saver';

const blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
FileSaver.saveAs(blob, "hello world.txt");

  

更多用法點擊官方文檔

批量獲取文件並打包下載

這兩個庫我們已經有所了解接下來就是實現我們的需求。這里分兩步進行,第一步是獲取文件;第二步是打包壓縮。

需要操作的源文件地址

這里的文件地址只是一個簡單的示例,實際開發的時候視情況而定。

const data = [
    {
        fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx',
        fileName: '文件一'
    },
    {
        fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx',
        fileName: '文件二'
    },
    {
        fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx',
        fileName: '文件三'
    },
    {
        fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx',
        fileName: '文件四'
    },
];  

  

獲取文件

import JSZip from 'jszip';
import FileSaver from 'file-saver';
import requestFile from './requestFile'; //這里是封裝的請求函數,大家用自己封裝的或者Axios都行

const getFile = (url: string) => {
  return new Promise((resolve, reject) => {
    requestFile(url, {
      method: 'GET',
      responseType: 'blob'
    }).then((res:any) => {
      resolve(res)
    }).catch((error: any) => {
      reject(error)
    })
  })
}

  

打包壓縮下載

這里主要是通過遍歷地址數組,然后通過地址從后端獲取文件,再進行一個批量壓縮打包文件的操作,最后把壓縮好的文件保存下來。

/**
 * 打包壓縮下載
 * @param data  源文件數組
 * @param fileName  壓縮文件的名稱
 */
const compressAndDownload = (data: any[], fileName ?: string) => {
  const zip = new JSZip();
  const promises: any[] = [];  //用於存儲多個promise
  data.forEach((item: any) => {
    const promise = getFile(item.fileUrl).then((res: any) => {
      const fileName = item.fileName
      zip.file(fileName, res ,{binary: true});
    })
    promises.push(promise)
  })

  Promise.all(promises).then(() => {
    zip.generateAsync({
      type: "blob",
      compression: "DEFLATE",  // STORE:默認不壓縮 DEFLATE:需要壓縮
      compressionOptions: {
        level: 9               // 壓縮等級1~9    1壓縮速度最快,9最優壓縮方式
      }
    }).then((res: any) => {
      FileSaver.saveAs(res, fileName ? fileName : "壓縮包.zip") // 利用file-saver保存文件
    })
  })
}

export default compressAndDownload;

 

 

 


免責聲明!

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



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