preface

Front-end file download I believe many partners are not unfamiliar, download the form of the file also have many, for example, the back end returns a file address, we put the address in the < A >
tag inside click download; Or we return the file stream through the back-end interface, and we do a series of operations on the stream and so on.

There are many solutions to single download, but when we need to batch download files, how do we do it?

plan

Faced with such demands, we proposed the following schemes:

Scheme 1: directly obtain the back-end file address array, and then one by one to download. However, each time a file is downloaded, the browser will show more downloading tasks;

Scheme 2: the back-end is used to package and compress files first, and then the front-end only needs to download a compressed file, but this will have a great impact on the server performance;

Plan three: or directly obtain the file address array returned by the back end, one by one to download, and then the front end to package compression processing.

To tell the truth, when it came to front-end packaging compression, I was like a part of my friends, how to front-end packaging compression? Here are two excellent libraries to solve our problem.

Here it is mentioned that the React environment is used as an example. However, the ideas and usage in other environments are basically the same. You can refer to the following content.

JSZip and FileSaver. Js

This section briefly introduces the APIS and usage of JSZip and Filesaver.js.

The installation

npm install jszip file-saver
Copy the code

JSZip

JSZip is a javascript library for creating, reading, and editing.zip files with a friendly and simple API.

A simple example

Let’s start by implementing a simple example to get a feel for this very useful tool

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()}}> download </button> </div>)} export default MyButtonCopy the code

Click the download button to get a compressed file named example.zip. Open the compressed file and there will also be a file named hello.txt.

API

A couple of apis.

Create JSZip instance:

const zip = new JSZip();
Copy the code

Create file:

zip.file("hello.txt"."Hello World\n");
Copy the code

Create folder:

zip.folder("file")
Copy the code

Create folders and files simultaneously:

zip.file("file/hello.txt"."Hello World\n");
/ / is equivalent to
zip.folder("file").file("hello.txt"."Hello World\n");

Copy the code

Generate a compressed file:

GenerateAsync (options) or.generatenodeStream (options) to generate a compressed file:

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

For details on the API, click on the official documentation

FileSaver.js

In the previous example we used JSZip and the filesaver.js library. FileSaver. Js is a solution for saving files on the client and is ideal for generating files on the client.

In the example in the previous section, we saved our.zip file using filesaver.js.

grammar

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

example

import FileSaver from 'file-saver'; const blob = new Blob(["Hello, world!"] , {type: "text/plain; charset=utf-8"}); FileSaver.saveAs(blob, "hello world.txt");Copy the code

Click on the official documentation for more usage

Get files in bulk and pack them for download

We’ve got a little bit of knowledge about these two libraries and the next step is to implement our requirements. Here in two steps, the first step is to get the file; The second step is package compression.

Address of the source file to operate

The file location here is just a simple example and depends on the actual development situation.

const data = [
    {
        fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx'.fileName: 'File 1'
    },
    {
        fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx'.fileName: 'Paper 2'
    },
    {
        fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx'.fileName: 'File 3'
    },
    {
        fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx'.fileName: 'Paper 4'},];Copy the code

Access to the file

import JSZip from 'jszip';
import FileSaver from 'file-saver';
import requestFile from './requestFile'; // Here is the wrapped request function, you can use your own wrapper or 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)
    })
  })
}
Copy the code

Packaged and compressed download

Here is mainly through the address array, and then through the address from the back end of the file, and then a batch compression package file operation, and finally the compressed file saved.

/** ** package compressed download *@param Data source file array *@param FileName Specifies the name of the compressed file */
const compressAndDownload = (data: any[], fileName ? : string) = > {
  const zip = new JSZip();
  const promises: any[] = [];  // Used to store multiple promises
  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 is not compressed by default
      compressionOptions: {
        level: 9               // Compression levels 1 to 9 1 Has the fastest compression speed and 9 has the best compression mode
      }
    }).then((res: any) = > {
      FileSaver.saveAs(res, fileName ? fileName : "Zip package. Zip") // Use file-saver to save the file})})}export default compressAndDownload;
Copy the code

reference

stuk.github.io/jszip/

Github.com/eligrey/Fil…

The last

By using JSZip and FileSaver. Js, we can pack and compress the batch files in the back end, which not only reduces the pressure on the server to some extent, but also gives people the feeling of downloading a file without many downloading tasks at one time, and improves the experience to some extent.