even

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
import JSZip from 'jszip';
import { extname, join, relative, sep, dirname } from 'path';
import { pathExists, Stats, stat, readdir, readFile, writeFile, ensureDir } from 'fs-extra';

/**
 * 递归文件执行回调函数
 * @param dirPath
 * @param handle
 * @returns
 */
const recursive = async (
    dirPath: string,
    handle: (file: string, ext: string, stat: Stats) => Promise<void>,
): Promise<void> => {
    if (!(await pathExists(dirPath))) return; // 如果路径不存在,直接返回

    const fileStats: Stats = await stat(dirPath);

    if (fileStats.isSymbolicLink()) return; // 如果是软链接,那么就直接跳过

    if (fileStats.isDirectory()) {
        const fileList = await readdir(dirPath, { withFileTypes: true });

        for (let i = 0, len = fileList.length; i < len; i++) {
            const temp = fileList[i];

            await recursive(join(dirPath, temp.name), handle);
        }
    } else if (fileStats.isFile()) {
        // 如果不存在需要过滤的,或者匹配上过虑的,那么执行回调
        await handle(dirPath, extname(dirPath), fileStats);
    }
};

/**
 * 实现文件压缩
 * @param {string} targetPath 目标路径
 * @param {string} destPath  压缩后的路径
 * @param {number} level 压缩等级
 */
export const zip = async (
    targetPath: string,
    destPath: string,
    level: number = 1,
): Promise<void> => {
    if (!(await pathExists(targetPath))) throw new Error('Zip requires a valid address');

    const zipHandle = new JSZip();
    // const folderName = basename(targetPath);

    await recursive(targetPath, async (file: string) => {
        const fileContent = await readFile(file);

        zipHandle
            // .folder(folderName)  //外面不需要再包一层文件夹
            ?.file(relative(targetPath, file).split(sep).join('/'), fileContent);
    });

    const buffer = await zipHandle.generateAsync({
        type: 'nodebuffer',
        compression: 'DEFLATE',
        compressionOptions: { level },
    });

    await writeFile(destPath, buffer);
};

/**
 * 实现zip文件解压
 * @param {string} targetPath 源文件地址
 * @param {string} destPath 目标地址
 */
export const unzip = async (targetPath: string, destPath: string): Promise<void> => {
    if (!(await pathExists(targetPath))) throw new Error('zip path is invalid');

    const zipHandle = new JSZip();

    const buffer = await readFile(targetPath);

    const handle: JSZip = await zipHandle.loadAsync(buffer, { createFolders: false });
    const { files } = handle;
    const keys = Object.keys(files);

    for (let i = 0, len = keys.length; i < len; i++) {
        const temp = join(destPath, keys[i]);
        await ensureDir(dirname(temp));

        if (!handle.files[keys[i]].dir) {
            const content = await handle.files[keys[i]].async('nodebuffer');

            await writeFile(temp, content);
        }
    }
};

 

posted on 2022-10-26 10:07  even_blogs  阅读(245)  评论(0编辑  收藏  举报