js實現根據文件url批量壓縮下載成zip包

前言

項目開發中,產品經理提瞭這樣一個需求:將系統中的附件實現批量打包下載功能。本來系統中是有單個下載及批量下載功能,現在應業務方的需求,需要多加個批量打包下載。
初步設想是:由後端編寫接口實現。但後來經過思考:現在系統中已經有文件的url地址瞭,何必讓後端寫接口重復,前端處理就行。

1. 所需包

  • jszip
  • file-saver
  • axios

JSZip 是一個用於創建、讀取和編輯 ZIP 文件的 JavaScript 庫,並且擁有有友好而簡單的API,可直接在瀏覽器上創建 zip 壓縮檔。

file-saver

2. 安裝

npm install jszip --save  /  yarn add jszip -S
npm install file-saver --save  / yarn add file-saver -S
// axios 相信大傢安裝的都有

3. 引入

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

4. 完整代碼解析使用

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. 部分代碼解析

const zip = new JSZip() // 創建實例對象
zip.file(fileName, res, {binary: true})
  • zip.file(name, content, options),用於創建文件,有三個參數,其中 name 為文件名,content 為文件內容
  • zip.folder(name),用於創建文件夾

這兩個函數都有返回值,返回值為 JSZip 對象,即可以鏈式調用

比如:創建一個text.txt 文件和 測試文件夾 ,測試文件夾下面又有一個text2.txt 文件,可以使用下面的鏈式寫法。

const zip = new JSZip()
zip.file('test.txt', '哈哈哈哈哈').folder('測試文件夾').file('text2.txt', '我是另一個文件')

在上面中,我們隻需用到 zip.file 即可。

zip.file 的第三個參數是選填,是一個對象,常見的值有: binarybase64 等,在這裡是將其設置為 { binary: true } 是為瞭返回二進制的數據。

解析 Bolb 與 arraybuffer

Blob 表示二進制類型的大對象,在 JavaScript 中 Blob 類型的對象表示不可變,

Blob 對象包含兩個屬性:sizetype

  • size 屬性用於表示數據的大小
  • type 是MIME 類型的字符串

如下圖,就是上面的 getFileData 方法打印出來的 Bolb 對象

在這裡插入圖片描述

ArrayBuffer 對象表示一段二進制數據,用來模擬內存裡的數據。通過這個對象,JavaScript 可以讀寫二進制數據,這個數據可以看做是內存數據的表達。

兩者區別:

  • Bolb 對象用於操作二進制文件,通常用來讀寫文件
  • ArrayBuffer 用於操作內存

如下圖,這個上面的文件使用 responseType: 'arraybuffer' 打印出的結果

在這裡插入圖片描述

到此這篇關於js實現根據文件url批量壓縮下載成zip包的文章就介紹到這瞭,更多相關js url批量壓縮下載成zip包內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: