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;

 

 

 

posted on 2021-06-08 18:38  ygunoil  阅读(1072)  评论(0编辑  收藏  举报