// import JsZip from 'jszip'; import type { DeflateOptions } from 'fflate' import { Zip, ZipDeflate, strToU8 } from 'fflate' import { getFileExt } from './file' export class FileInfo { name: string content: string | Blob | Uint8Array encode: string = 'UTF-8' isBase64 = false binary = false constructor(name, text, isBase64 = false) { this.name = name this.content = text this.isBase64 = isBase64 } } export abstract class ZipProvider { // abstract loadAsync(file: File): Promise; protected files: FileInfo[] = [] addFile(file: FileInfo) { this.files.push(file) } abstract saveAsync(): Promise } // export class JsZipProvider extends ZipProvider // { // private ctx = new JsZip(); // // async loadAsync(file: File): Promise // // { // // await this.ctx.loadAsync(file); // // } // async saveAsync(): Promise // { // for (const file of this.files) // { // this.ctx.file(file.name, file.content, { // createFolders: true, // base64: file.isBase64, // binary: file.binary, // compression: "DEFLATE", // }); // } // return await this.ctx.generateAsync({ type: 'blob' }); // } // } export class FflateZipProvider extends ZipProvider { private ctx = new Zip() private task: Promise constructor() { super() this.task = new Promise((resolve, reject) => { let result = [] this.ctx.ondata = (err, data, final) => { if (!err) { result.push(data) if (final) { resolve(new Blob(result, { type: 'application/zip' })) } } else { reject() } } }) } async saveAsync(): Promise { for (const file of this.files) { let data: Uint8Array if (file.content instanceof Blob) { // console.log(file.name); let buffer = await file.content.arrayBuffer() // console.log('buffer', buffer); data = new Uint8Array(buffer) } else if (file.content instanceof Uint8Array) { data = file.content } else if (file.isBase64) { data = new Uint8Array(atob(file.content).split('').map((c) => { return c.charCodeAt(0) })) } else { data = strToU8(file.content) } let zipInput = new ZipDeflate(file.name, this.getOptionByExt(file.name)) this.ctx.add(zipInput) zipInput.push(data, true) } this.ctx.end() return this.task } getOptionByExt(fileName: string) { let option: DeflateOptions = { level: 6, // mem: 12 } let ext = getFileExt(fileName) if (ext !== null) { switch (ext) { case 'bmp': option.level = 1 option.mem = 0 break case 'jpg': case 'jpeg': option.level = 1 break case 'png': option.level = 0 break } } return option } } export const DefaultZipProvider = () => new FflateZipProvider()