C#压缩文件夹时如何实现压缩过程的中途取消功能
支持中途取消的文件夹Zip压缩实现
核心需求是对文件夹执行压缩时,可以在压缩执行过程中随时终止操作,最合理的实现方式是给压缩方法传入CancellationToken参数,从方法外部触发取消逻辑。
原生方法的局限
System.IO.Compression命名空间提供了内置的Zip压缩方法,但原生的ZipFile.CreateFromDirectory不支持传入取消令牌,无法中途撤销压缩操作。目前常见的替代方案只能等压缩全程执行完成后,再删除生成的无效压缩包,会造成不必要的资源开销。
原生方法的调用示例如下:
string startPath = @"<path-to-folder>"; string zipPath = @"<path-to-output>\MyFileZip.zip"; ZipFile.CreateFromDirectory(startPath, zipPath); // 无法传入CancellationToken实现中途取消
可落地的实现方案
手动逐文件写入Zip压缩包,在每一步操作前检查取消令牌状态,同时在文件流拷贝时传入令牌,就能实现全流程的取消响应:
using System.IO.Compression; public static void CreateCancellableZip(string sourceFolderPath, string outputZipPath, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // 初始化压缩文件流与压缩包实例 using var zipFileStream = new FileStream(outputZipPath, FileMode.Create, FileAccess.Write); using var zipArchive = new ZipArchive(zipFileStream, ZipArchiveMode.Create, leaveOpen: false); // 递归遍历源目录下的所有文件 foreach (var filePath in Directory.EnumerateFiles(sourceFolderPath, "*", SearchOption.AllDirectories)) { // 处理每个文件前先检查取消信号 cancellationToken.ThrowIfCancellationRequested(); // 计算文件在压缩包内的相对存储路径 var entryRelativePath = Path.GetRelativePath(sourceFolderPath, filePath); var zipEntry = zipArchive.CreateEntry(entryRelativePath, CompressionLevel.Optimal); // 打开文件流与压缩条目流,写入时传入取消令牌,支持大文件写入过程中响应取消 using var entryStream = zipEntry.Open(); using var sourceFileStream = File.OpenRead(filePath); sourceFileStream.CopyTo(entryStream, cancellationToken); } }
使用注意事项
- 触发取消时方法会抛出
OperationCanceledException,可在调用层捕获该异常,按需删除未生成完成的损坏压缩包 - 遍历文件前、单个文件处理前、流拷贝过程三层检查取消信号,无论是小文件多的场景还是单个超大文件的场景,都能快速响应取消操作
- 所有流对象均采用
using声明,取消触发时会自动释放所有文件句柄,不会出现资源占用或文件锁问题
内容的提问来源于stack exchange,提问作者simple_developer
相关产品推荐
相关产品推荐

