Bra*_*ray 5 .net c# asp.net .net-4.5
我正在尝试创建任意大小的zip文件.zip存档的来源是一堆URL,可能很大(列表中有500个4MB JPG).我希望能够在请求中执行所有操作并立即开始下载,并在构建时创建zip并进行流式处理.它不应该驻留在服务器的内存或磁盘上.
我最接近的是:注意:urls是文件名的URL的键值对,因为它们应该存在于创建的zip中
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/zip";
Response.AddHeader("Content-Disposition", "attachment; filename=DyanmicZipFile.zip");
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
foreach (KeyValuePair<string, string> fileNamePair in urls)
{
var zipEntry = archive.CreateEntry(fileNamePair.Key);
using (var entryStream = zipEntry.Open())
using (WebClient wc = new WebClient())
wc.OpenRead(GetUrlForEntryName(fileNamePair.Key)).CopyTo(entryStream);
//this doesn't work either
//using (var streamWriter = new StreamWriter(entryStream))
// using (WebClient wc = new WebClient())
// streamWriter.Write(wc.OpenRead(GetUrlForEntryName(fileNamePair.Key)));
}
}
memoryStream.WriteTo(Response.OutputStream);
}
HttpContext.Current.ApplicationInstance.CompleteRequest();
Run Code Online (Sandbox Code Playgroud)
这段代码给了我一个zip文件,但是zip里面的每个JPG文件只是一个文本文件,上面写着"System.Net.ConnectStream"我还有其他的尝试,用它来构建一个带有正确文件的zip文件,但是你可以通过开始时的延迟告诉服务器完全在内存中构建zip,然后在最后将其压缩.当文件计数接近50时,它根本没有响应.评论中的部分给了我同样的结果我也尝试了Ionic.Zip.
这是IIS8上的.NET 4.5.我正在使用VS2013构建并尝试在AWS Elastic Beanstalk上运行它.
因此,回答我自己的问题 - 这是适合我的解决方案:
private void ProcessWithSharpZipLib()
{
byte[] buffer = new byte[4096];
ICSharpCode.SharpZipLib.Zip.ZipOutputStream zipOutputStream = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(Response.OutputStream);
zipOutputStream.SetLevel(0); //0-9, 9 being the highest level of compression
zipOutputStream.UseZip64 = ICSharpCode.SharpZipLib.Zip.UseZip64.Off;
foreach (KeyValuePair<string, string> fileNamePair in urls)
{
using (WebClient wc = new WebClient())
{
using (Stream wcStream = wc.OpenRead(GetUrlForEntryName(fileNamePair.Key)))
{
ICSharpCode.SharpZipLib.Zip.ZipEntry entry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(ICSharpCode.SharpZipLib.Zip.ZipEntry.CleanName(fileNamePair.Key));
zipOutputStream.PutNextEntry(entry);
int count = wcStream.Read(buffer, 0, buffer.Length);
while (count > 0)
{
zipOutputStream.Write(buffer, 0, count);
count = wcStream.Read(buffer, 0, buffer.Length);
if (!Response.IsClientConnected)
{
break;
}
Response.Flush();
}
}
}
}
zipOutputStream.Close();
Response.Flush();
Response.End();
}
Run Code Online (Sandbox Code Playgroud)