152 lines
3.1 KiB
TypeScript
152 lines
3.1 KiB
TypeScript
|
// 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<void>;
|
||
|
protected files: FileInfo[] = []
|
||
|
|
||
|
addFile(file: FileInfo)
|
||
|
{
|
||
|
this.files.push(file)
|
||
|
}
|
||
|
|
||
|
abstract saveAsync(): Promise<Blob>
|
||
|
}
|
||
|
|
||
|
// export class JsZipProvider extends ZipProvider
|
||
|
// {
|
||
|
|
||
|
// private ctx = new JsZip();
|
||
|
|
||
|
// // async loadAsync(file: File): Promise<void>
|
||
|
// // {
|
||
|
// // await this.ctx.loadAsync(file);
|
||
|
// // }
|
||
|
|
||
|
// async saveAsync(): Promise<Blob>
|
||
|
// {
|
||
|
// 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<Blob>
|
||
|
|
||
|
constructor()
|
||
|
{
|
||
|
super()
|
||
|
this.task = new Promise<Blob>((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<Blob>
|
||
|
{
|
||
|
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()
|