123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- const fs = require('fs');
- const path = require('path');
- const archiver = require('archiver');
- const cliProgress = require('cli-progress');
- const { minimatch } = require('minimatch');
- // 定义忽略模式
- const ignorePatterns = [
- 'node_modules/**', // 排除 node_modules 目录
- 'dist.zip', // 排除 dist.zip 文件
- '.idea/**', // 排除 .idea 目录
- '.vscode/**', // 排除 .vscode 目录
- '.git/**', // 排除 .git 目录
- 'build.js', // 排除 build.js 文件
- 'server.js', // 排除 server.js 文件
- 'package-lock.json', // 排除 package-lock.json 文件
- 'package.json', // 排除 package.json 文件
- ];
- // 定义源目录和目标压缩文件路径
- const sourceDir = './';
- const outputZipPath = path.join(sourceDir, 'dist.zip');
- // 创建进度条
- const progressBar = new cliProgress.SingleBar({
- format: '进度: {bar} {percentage}% | {value}/{total} MB',
- barCompleteChar: '\u2588',
- barIncompleteChar: '\u2591',
- hideCursor: true,
- barComplete: '\u001b[32m\u2588\u001b[0m', // 绿色完成部分
- barIncomplete: '\u001b[31m\u2591\u001b[0m', // 红色未完成部分
- complete: '\u001b[32m#\u001b[0m', // 绿色完成字符
- incomplete: '\u001b[31m#\u001b[0m' // 红色未完成字符
- }, cliProgress.Presets.shades_classic);
- // 计算总文件大小(以字节为单位)
- function getTotalFileSize(dir, ignorePatterns) {
- let totalSize = 0;
- function walk(dir, isTopLevel = true) {
- const files = fs.readdirSync(dir);
- files.forEach((file) => {
- const filePath = path.join(dir, file);
- const stat = fs.statSync(filePath);
- if (stat.isDirectory()) {
- // 只在第一级时检查忽略目录
- if (isTopLevel && ignorePatterns.some(pattern => minimatch(filePath, pattern, { matchBase: true }))) {
- return;
- }
- walk(filePath, false);
- } else {
- // 检查是否需要忽略文件(非第一级时也检查)
- if (!ignorePatterns.some(pattern => minimatch(filePath, pattern, { matchBase: true }))) {
- totalSize += stat.size;
- }
- }
- });
- }
- walk(dir);
- return totalSize;
- }
- // 计算总文件大小
- const totalFileSize = getTotalFileSize(sourceDir, ignorePatterns);
- // 创建一个输出流
- const output = fs.createWriteStream(outputZipPath);
- const archive = archiver('zip', {
- zlib: { level: 9 } // 设置压缩级别
- });
- // 标记进度条是否已经启动
- let progressBarStarted = false;
- let processedSize = 0;
- // 监听输出流的事件
- output.on('close', () => {
- progressBar.stop();
- console.log(`压缩完成: ${(archive.pointer() / (1024 * 1024)).toFixed(1)} MB`);
- });
- output.on('end', () => {
- console.log('数据传输完成');
- });
- // 监听归档过程中的错误
- archive.on('warning', (err) => {
- if (err.code === 'ENOENT') {
- // 文件不存在的警告
- console.warn(err);
- } else {
- // 其他警告
- throw err;
- }
- });
- archive.on('error', (err) => {
- throw err;
- });
- // 监听归档开始事件
- archive.on('entry', (entry) => {
- const filePath = path.join(sourceDir, entry.name);
- const stat = fs.statSync(filePath);
- processedSize += stat.size;
- if (!progressBarStarted) {
- const totalMB = parseFloat((totalFileSize / (1024 * 1024)).toFixed(1));
- const processedMB = parseFloat((processedSize / (1024 * 1024)).toFixed(1));
- progressBar.start(totalMB, processedMB);
- progressBarStarted = true;
- } else {
- const processedMB = parseFloat((processedSize / (1024 * 1024)).toFixed(1));
- progressBar.update(processedMB);
- }
- });
- // 将输出流管道到归档器
- archive.pipe(output);
- // 添加源目录中的所有文件到归档,排除特定文件或目录
- archive.glob('**/*', {
- cwd: sourceDir,
- ignore: ignorePatterns
- });
- // 完成归档
- archive.finalize();
|