我们的应用程序在Docker中运行,每个进程中可用的内存有限。我们使用大型文件并对其进行压缩,因此习惯上将FileStreams与FileOptions.DeleteOnClose选项一起用作临时流。
当我们创建一个zip文件时,我们会创建一个临时文件流,使用ZipArchive写入该流,处理该ZipArchive,后退该流,并将该流的内容复制到诸如Mongo GridFS的持久存储中。我们遇到的问题是持久性存储中的zip文件是无效的zip文件。
为了找出问题,我们创建了一个持久的“临时”文件流,并在处理ZipArchive之后和在处理文件流之后检查其有效性。我们看到的是ZipArchive Dispose()之后的文件流是一个无效的zip文件,但是在Filestream 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 / final和delete包裹的持久性临时文件流。内存流也不是可行的解决方案。
更改行实例化archive
:
using var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true);
至:
using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
否则,您将流处理混乱,导致描述的行为。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句