我有一个包含zip文件的网址。需要从URL解压缩文件。 URL使用webclient打开并读取,然后添加到Stream。然后在ZipArchive对象中使用它,它将解压缩文件并将它们存储在D:\驱动器中。当文件大约400Mb时,我得到'System.OutOfMemoryException'。
必须使用Stream,因为webClient.OpenRead(Uri Address)返回一个Stream。以及使用ZipArchive(Stream stream)。
如何停止收到此消息?
string zipFileUrl = "https://www.dropbox.com/s/clersbjdcshpdy6/oversize_zip_test_0.zip?dl=0"
string output_path = @"D:\";
using (WebClient webClient = new WebClient())
{
using (Stream streamFile = webClient.OpenRead(zipFileUrl))
{
using (ZipArchive archive = new ZipArchive(streamFile))//ERROR HERE
{
var entries = archive.Entries;
//Loops thru each file in Zip and adds it to directory
foreach (var entry in entries)
{
if (entry.FullName != "/" && entry.Name != "")
{
string completeFileName = Path.Combine(output_path, entry.FullName);
string directory = Path.GetDirectoryName(completeFileName);
//If directory does not exist then we create it.
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
//Extracts zip from URL to extract path, and overwrites if file exists.
entry.ExtractToFile(completeFileName, true);
}
}
}
}
答案 0 :(得分:4)
我认为here might be your problem来自ZipArchive.Init
方法
private void Init(Stream stream, ZipArchiveMode mode, Boolean leaveOpen)
{
Stream extraTempStream = null;
try
{
_backingStream = null;
//check stream against mode
switch (mode)
{
case ZipArchiveMode.Create:
// (SNIP)
case ZipArchiveMode.Read:
if (!stream.CanRead)
throw new ArgumentException(SR.ReadModeCapabilities);
if (!stream.CanSeek)
{
_backingStream = stream;
extraTempStream = stream = new MemoryStream();
_backingStream.CopyTo(stream);
stream.Seek(0, SeekOrigin.Begin);
}
break;
case ZipArchiveMode.Update:
// (SNIP)
default:
// (SNIP)
}
// (SNIP)
}
如果streamFile.CanSeek
为false(从WebClient开始),它会将整个文件复制到内存中然后处理该文件。这就是耗尽所有内存的东西。
尝试查找处理Zip文件的第三方库,并且不需要支持搜索的流。如果不能,请先将文件复制到磁盘文件夹,并将FileStream
传入FileOptions.DeleteOnClose
选项,然后在关闭流之前在zip中使用该流。
string zipFileUrl = "https://www.dropbox.com/s/clersbjdcshpdy6/oversize_zip_test_0.zip?dl=0";
string output_path = @"D:\";
using (var tempFileStream = new FileStream(Path.GetTempFileName(), FileMode.Create,
FileAccess.ReadWrite, FileShare.None,
4096, FileOptions.DeleteOnClose))
{
using (WebClient webClient = new WebClient())
{
using (Stream streamFile = webClient.OpenRead(zipFileUrl))
{
streamFile.CopyTo(tempFileStream);
}
}
tempFileStream.Position = 0;
using (ZipArchive archive = new ZipArchive(tempFileStream))
{
var entries = archive.Entries;
//Loops thru each file in Zip and adds it to directory
foreach (var entry in entries)
{
if (entry.FullName != "/" && entry.Name != "")
{
string completeFileName = Path.Combine(output_path, entry.FullName);
string directory = Path.GetDirectoryName(completeFileName);
//If directory does not exist then we create it.
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
//Extracts zip from URL to extract path, and overwrites if file exists.
entry.ExtractToFile(completeFileName, true);
}
}
}
}