Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Streaming a zip file over http in .net with SharpZipLib

I'm making a simple download service so a user can download all his images from out site. To do that i just zip everything to the http stream.

However it seems everything is stored in memory, and the data isn't sent til zip file is complete and the output closed. I want the service to start sending at once, and not use too much memory.

public void ProcessRequest(HttpContext context)
{
    List<string> fileNames = GetFileNames();
    context.Response.ContentType = "application/x-zip-compressed";
    context.Response.AppendHeader("content-disposition", "attachment; filename=files.zip");
    context.Response.ContentEncoding = Encoding.Default;
    context.Response.Charset = "";

    byte[] buffer = new byte[1024 * 8];

    using (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zipOutput = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(context.Response.OutputStream))
    {
        foreach (string fileName in fileNames)
        {
            ICSharpCode.SharpZipLib.Zip.ZipEntry zipEntry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(fileName);
            zipOutput.PutNextEntry(zipEntry);
            using (var fread = System.IO.File.OpenRead(fileName))
            {
                ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(fread, zipOutput, buffer);
            }
        }
        zipOutput.Finish();
    }

    context.Response.Flush();
    context.Response.End();
}

I can see the the worker process memory growing while it makes the file, and then releases the memory when its done sending. How do i do this without using too much memory?

like image 823
AndreasN Avatar asked Mar 09 '09 13:03

AndreasN


1 Answers

Disable response buffering with context.Response.BufferOutput = false; and remove the Flush call from the end of your code.

like image 144
Jon Skeet Avatar answered Oct 08 '22 07:10

Jon Skeet