ZipArchive 无效的 Zip 文件
ZipArchive Invalid Zip File
我们的应用在 Docker 中 运行,每个进程的可用内存有限。我们处理和压缩大文件,因此习惯上使用 FileStreams 作为带有 FileOptions.DeleteOnClose 选项的临时流。
当我们创建一个 zip 文件时,我们会创建一个临时文件流,使用 ZipArchive 写入流,处理 ZipArchive,倒带流,并将流的内容复制到某个持久存储,如 Mongo GridFS .我们遇到的问题 运行 是持久存储中的 zip 文件是无效的 zip 文件。
为了隔离问题,我们创建了一个持久的 'temporary' 文件流,并在我们处理 ZipArchive 和处理文件流后检查它的有效性。我们看到的是 ZipArchive Dispose() 之后的文件流是一个无效的 zip 文件,但在文件流 Dispose() 之后它是一个有效的流。处理文件流后,磁盘上的长度与处理前的长度不匹配。为什么磁盘上的文件在处理文件流之前不是有效的 zip 文件?
[Test]
public async Task ZipFile2()
{
string zipPath = Path.Combine(Path.GetTempPath(), "test.zip");
long streamLengthBeforeClose;
using (var sourceFile = new FileStream("../../../../Foundations.Blob.UnitTests/TestData/test-file.txt", FileMode.Open))
using (var zipStream = new FileStream(zipPath, FileMode.Create))
{
using var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true);
{
var entry = archive.CreateEntry("test-file.txt");
using (var entryStream = entry.Open())
{
// copy from the blob to the zip entry
await sourceFile.CopyToAsync(entryStream, CancellationToken.None);
}
}
zipStream.Flush();
// at this point the zipStream IS NOT A VALID ZIP FILE
streamLengthBeforeClose = zipStream.Length;
}
// at this point the zipStream IS A VALID ZIP FILE
var fi = new FileInfo(zipPath);
// These do not match
Assert.AreEqual(streamLengthBeforeClose, fi.Length);
}
注意:我们不想使用用 try/finally 包裹的永久性临时文件流和删除。内存流也不是可行的解决方案。
更改行实例化archive
:
using var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true);
收件人:
using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
否则,您会将流处理混淆,从而导致所描述的行为。
我们的应用在 Docker 中 运行,每个进程的可用内存有限。我们处理和压缩大文件,因此习惯上使用 FileStreams 作为带有 FileOptions.DeleteOnClose 选项的临时流。
当我们创建一个 zip 文件时,我们会创建一个临时文件流,使用 ZipArchive 写入流,处理 ZipArchive,倒带流,并将流的内容复制到某个持久存储,如 Mongo GridFS .我们遇到的问题 运行 是持久存储中的 zip 文件是无效的 zip 文件。
为了隔离问题,我们创建了一个持久的 'temporary' 文件流,并在我们处理 ZipArchive 和处理文件流后检查它的有效性。我们看到的是 ZipArchive Dispose() 之后的文件流是一个无效的 zip 文件,但在文件流 Dispose() 之后它是一个有效的流。处理文件流后,磁盘上的长度与处理前的长度不匹配。为什么磁盘上的文件在处理文件流之前不是有效的 zip 文件?
[Test]
public async Task ZipFile2()
{
string zipPath = Path.Combine(Path.GetTempPath(), "test.zip");
long streamLengthBeforeClose;
using (var sourceFile = new FileStream("../../../../Foundations.Blob.UnitTests/TestData/test-file.txt", FileMode.Open))
using (var zipStream = new FileStream(zipPath, FileMode.Create))
{
using var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true);
{
var entry = archive.CreateEntry("test-file.txt");
using (var entryStream = entry.Open())
{
// copy from the blob to the zip entry
await sourceFile.CopyToAsync(entryStream, CancellationToken.None);
}
}
zipStream.Flush();
// at this point the zipStream IS NOT A VALID ZIP FILE
streamLengthBeforeClose = zipStream.Length;
}
// at this point the zipStream IS A VALID ZIP FILE
var fi = new FileInfo(zipPath);
// These do not match
Assert.AreEqual(streamLengthBeforeClose, fi.Length);
}
注意:我们不想使用用 try/finally 包裹的永久性临时文件流和删除。内存流也不是可行的解决方案。
更改行实例化archive
:
using var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true);
收件人:
using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
否则,您会将流处理混淆,从而导致所描述的行为。