动态创建一堆URL的动态zip

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上运行它.

Bra*_*ray 1

因此,回答我自己的问题 - 这是适合我的解决方案:

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)