使用 Ionic 创建大型多部分 zip 失败并出现 OutOfMemoryException
Posted
技术标签:
【中文标题】使用 Ionic 创建大型多部分 zip 失败并出现 OutOfMemoryException【英文标题】:Creating large multi-part zip with Ionic fails with OutOfMemoryException 【发布时间】:2016-08-19 06:59:31 【问题描述】:我尝试使用 IonicZip 创建一个包含总大小为 17 GB 的文件的多部分 zip 文件。
每个 zip 部分设置为不大于 500 MB 左右。
zip.MaxOutputSegmentSize = 500000000;
进入 zip 的文件大小不一,但从不超过 350MB,通常小得多,只有几 KB 或 MB。
我创建 zip 文件的机器有 4GB 内存。
当我在我的程序中开始创建 zip 时,由于使用了 RAM,我有时会收到一个 OutOfMemoryException
。
(当所有文件的总大小约为 2 GB 而不是 17 GB 时,同样可以正常工作)。
代码:
ZipFile zip = new ZipFile(zipFileName, Encoding.UTF8);
zip.CompressionLevel = CompressionLevel.BestCompression;
zip.ParallelDeflateThreshold = -1; // https://***.com/questions/11981143/compression-fails-when-using-ionic-zip
zip.MaxOutputSegmentSize = 500000000; // around 500MB
[...]
while (...)
zip.AddEntry(adjustedFilePath, File.ReadAllBytes(filepath));
zip.Save();
我想知道 IonicZip 如何结合多部分创建处理 zip.save。不必将所有多部分保存在内存中,而只保存当前部分,不是吗?
由于我将 zip.MaxOutputSegmentSize 设置为仅 500MB 左右,并且进入 zip 的单个文件的最大大小从不超过 350MB,我不明白为什么它会占用这么多内存。
另一方面,当 OutOfMemoryException 发生时,甚至还没有多部分的任何单个部分写入磁盘。通常,当 zip 创建成功的文件数量较少时,多个部分在文件系统上具有不同的创建时间戳,大约每次间隔 5 秒。所以我真的不确定 IonicZip 在内部到底在做什么,直到它吐出第一个 zip 部分。
抱歉,我是 C# 和 .NET 的新手。 IonicZip 是最好的库吗?我可以改用 System.IO.Compression 或 System.IO.Packaging 包(我没有看到它们支持多部分 zip)或商业 Xceed?
我已经检查过但没有帮助的帖子:
Compression fails when using ionic zip Ionic zip throws out of memory exception OutOfMemoryException when creating large ZIP file using System.IO.Packaging(与 IonicZip 无关)【问题讨论】:
【参考方案1】:我建议使用内置的 .net System.IO.Compression 命名空间类来压缩/解压缩文件;它们是基于流的,而您在此处的示例不使用流-因此必须使用 RAM 来存储压缩数据。使用 .net 原生库,您可以将压缩数据分块写入输出流。
【讨论】:
谢谢。这个包是否支持多部分拉链,因为我在 Google 或 msdn.microsoft.com/de-de/library/… 中找不到任何关于它的信息 Zip 支持,但其他 (GZip) 不支持。 您能否指出一些可以设置拆分大小的在线 API 文档?我仍然看不到我可以通过System.IO.Compression
包做到这一点。现在我正在测试 Xceed (xceed.com/xceed-zip-for-net) 库作为替代方案,我可以简单地说 zip.splitSize= 500000000
。到目前为止,我看不到内存使用量有任何增加,但它仍在压缩我的 17GB。
抱歉 - 我不知道 SplitSize 是什么或它的用途。
创建一个多部分的 zip 文件。由于我需要压缩 17GB 的文件,我不想有一个大的 zip 文件,而是分成多个,所以最后我会有 myfiles.zip、myfiles.z01、myfiles.z01 等每个不大于 500MB。特别是因为 zip 格式每个文件的大小限制为 4GB。 “SplitSize”只是 Xceed 用来定义此类零件的最大尺寸的参数名称。在 IonicZip 中,它被称为“MaxOutputSegmentSize”。【参考方案2】:
我想出的解决方案在努力方面似乎是最好的(我不想重新发明***并为标准 zip/压缩包编写多部分逻辑,这似乎是一个标准的事情这应该是任何压缩包的一部分)是使用Xceed,并且几乎使用与 IonicZip 相同的代码逻辑。
似乎 IonicZip 在内存方面并没有真正以有效的方式处理它。 Xceed 运行良好,没有显着增加内存使用量。
using Xceed.Zip;
using Xceed.FileSystem;
[...]
ZipArchive zip = new ZipArchive(new DiskFile(zipFileName));
zip.SplitNameFormat = SplitNameFormat.PkZip;
zip.SplitSize = 500000;
zip.DefaultCompressionLevel = Xceed.Compression.CompressionLevel.Highest;
zip.TempFolder = new DiskFolder(@"C:\temp");
new DiskFolder(localSourceFolder).CopyFilesTo(zip, true, true);
【讨论】:
以上是关于使用 Ionic 创建大型多部分 zip 失败并出现 OutOfMemoryException的主要内容,如果未能解决你的问题,请参考以下文章
如何创建具有低 memory_limit 的大型 zip 文件?
失败 - 在 chrome 中获取 Zip 文件时出现网络错误
如何在 C# 中使用 Ionic-zip 下载大文件时修复 zip 文件损坏错误
Gradle distributionUrl 使用“ionic cordova run android”更改为旧版本,构建失败