The front-end js implements batch compression and downloading into zip packages according to the file url

foreword

During the project development, the product manager raised such a requirement: to realize the function of batch packaging and downloading the attachments in the system. Originally, the system had single download and batch download functions, but now in response to the needs of the business side, it is necessary to add a batch package download.
The initial idea is: the interface is written by the back end. But after thinking about it later: Now that the url address of the file already exists in the system, why bother to repeat the back-end writing interface, and the front-end processing is enough.

1. Required packages

  • jszip
  • file-saver
  • axios

JSZipis a JavaScript library for creating, reading and editing ZIP files, and has a friendly and simple API to create zip archives directly on the browser.

file-saver

2. Install

npm install jszip --save  /  yarn add jszip -S

npm install file-saver --save  / yarn add file-saver -S

// axios 相信大家安装的都有

3. Import

import JSZip from 'jszip'
import FileSaver from 'file-saver'
import axios from 'axios';

4. Complete code analysis and use

import React, {
    
     memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';

import JSZip from 'jszip'
import FileSaver from 'file-saver'
import axios from 'axios';

// 在这里定义一个数据源,格式为 文件url + 文件名,可以根据自己的项目获取
const dataSouce = [
	{
    
    
        fileUrl: 'http://dev.imuyuan.com/file/fetch/v1/7lGQFepQllMVl8ZTbMftS5',
        fileName: '文件一'
    },
    {
    
    
        fileUrl: 'http://dev.imuyuan.com/file/fetch/v1/5SNVT9QI6g791pHBSjLRsE',
        fileName: '文件二'
    },
    {
    
    
        fileUrl: 'http://dev.imuyuan.com/file/fetch/v1/4m0Qy7k1qMrh8QIA8DbHce',
        fileName: '文件三'
    },
    {
    
    
        fileUrl: 'http://dev.imuyuan.com/file/fetch/v1/2GCtdxKkrlVTSHAt00sHXJ',
        fileName: '文件四'
    },
]

const Index = () => {
    
    

	// 将文件 url 格式转换为 Bolb 类型格式 或者 arraybuffer 格式
	const getFileData = (fileUrl: string) => {
    
    
		return new Promise((resolve, reject) => {
    
    
			axios(fileUrl, {
    
    
				method: 'GET',
				responseType: 'blob'  // 返回的数据会被强制转为blob类型 ,转换成arraybuffer 也行
			}).then((res) => {
    
    
				console.log('res', res)
				resolve(res)
			}).catch(error) => {
    
    
				reject(error)
			}
		})
	}
	
	// 批量打包下载事件
	const handleBatchDown = async () => {
    
    
		const zip = new JSZip() // 创建实例对象
		const promises: any = []
		dataSource.forEach((item: any) => {
    
    
			const promise = getFile(item.fileUrl).then((res: any) => {
    
    
				const fileName = item.fileName + ''
				// 创建文件用file(),创建文件夹用 floder()
				zip.file(fileName, res, {
    
    binary: true})
			})
			promises.push(promise)
		})
		
		/** 
			Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例,
			只有当all([p1, p2, p3]) 中的每一个 Promise 实例的状态都变成 fulfilled, Promise.all()的状态才会变成 fulfilled,此时  p1, p2, p3 的返回值组成一个数据,传给 Promise.all()的回调函数
			只要 p1, p2, p3 中任何一个被 rejected,  Promise.all() 的状态就会变成 rejected,此时第一个被 rejected 的实例的返回值,会传给 Promise.all()的回调函数。
			
			在上面的代码中,promises 数组中的每一个元素,都是 Promise 实例,所以需要用到 Promise.all()	
		*/
		
		// 生成 zip 文件
		Promise.all(promises).then(() => {
    
    
			// 生成zip 文件
			zip.generateAsync({
    
    
				type: 'blob',
				compression: 'DEFLATE',  // STORE: 默认不压缩, DEFLATE:需要压缩
         		compressionOptions: {
    
    
           			level: 9          // 压缩等级 1~9   1 压缩速度最快, 9 最优压缩方式
         		}
			}).then((res: any) => {
    
    
				FileSaver.saveAs(res, '测试.zip') // 使用FileSaver.saveAs保存文件,文件名可自定义
			})
		})
		
	}
	
	return (
		<div>
			<Button onClick = {
    
    handleBatchDown}>批量打包下载文件</Button>
		</div>
	)
}

export default memo(Index)

5. Partial code analysis

const zip = new JSZip() // 创建实例对象
zip.file(fileName, res, {
    
    binary: true})
  • zip.file(name, content, options), used to create a file, there are three parameters, where name is the file name, content is the content of the file
  • zip.folder(name), used to create a folder

These two functions have a return value, and the return value is JSZipan object , that is, they can be called in a chain

For example: create a text.txt file and a test folder, and a text2.txt file under the test folder, you can use the following chain writing method.

const zip = new JSZip()
zip.file('test.txt', '哈哈哈哈哈').folder('测试文件夹').file('text2.txt', '我是另一个文件')

In the above, we only need to zip.fileuse .

zip.fileThe third parameter of is optional, which is an object. The common values ​​are: binary, base64etc. Here it is set to { binary: true } to return binary data.

Parsing Bolb and arraybuffer

  • BlobRepresents a large object of binary type. In JavaScript, an object of Blob type represents immutability.

The Blob object contains two properties: size,type

  • The size attribute is used to indicate the size of the data
  • type is a MIME type string

As shown in the figure below, it is the Bolb object printed by the above getFileDatamethod

insert image description here

  • ArrayBufferAn object represents a piece of binary data and is used to simulate data in memory. Through this object, JavaScript can read and write binary data, which can be regarded as the expression of memory data.

The difference between the two:

  • Bolb objects are used to manipulate binary files, usually used to read and write files
  • ArrayBuffer is used to manipulate memory

As shown in the figure below, the above file uses responseType: 'arraybuffer'the printed result

insert image description here

Guess you like

Origin blog.csdn.net/qq_41131745/article/details/128874556