Pregunta

Estoy creando un servicio de descarga simple para que un usuario pueda descargar todas sus imágenes desde el sitio. Para hacer eso, simplemente comprimo todo en la secuencia http.

Sin embargo, parece que todo está almacenado en la memoria, y los datos no se envían hasta que se completa el archivo zip y se cierra la salida. Quiero que el servicio comience a enviarse a la vez y no use demasiada memoria.

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();
}

Puedo ver el crecimiento de la memoria del proceso de trabajo mientras se crea el archivo, y luego libera la memoria cuando se realiza el envío. ¿Cómo hago esto sin usar demasiada memoria?

¿Fue útil?

Solución

Deshabilitar el búfer de respuesta con context.Response.BufferOutput = false; y elimina la llamada Flush del final de tu código.

Otros consejos

use Response.BufferOutput = false; al inicio de ProcessRequest y vaciar la respuesta después de cada archivo.

Para tu información. Este es un código de trabajo para agregar recursivamente un árbol completo de archivos, con transmisión al navegador:

string path = @"c:\files";

Response.Clear();
Response.ContentType = "application/zip";
Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", "hive.zip"));
Response.BufferOutput = false;

byte[] buffer = new byte[1024 * 1024];
using (ZipOutputStream zo = new ZipOutputStream(Response.OutputStream, 1024 * 1024)) {
    zo.SetLevel(0);
    DirectoryInfo di = new DirectoryInfo(path);
    foreach (string file in Directory.GetFiles(di.FullName, "*.*", SearchOption.AllDirectories)) {
        string folder = Path.GetDirectoryName(file);
        if (folder.Length > di.FullName.Length) {
            folder = folder.Substring(di.FullName.Length).Trim('\\') + @"\";
        } else {
            folder = string.Empty;
        }
        zo.PutNextEntry(new ZipEntry(folder + Path.GetFileName(file)));
        using (FileStream fs = File.OpenRead(file)) {
            ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(fs, zo, buffer);
        }
        zo.Flush();
        Response.Flush();
    }
    zo.Finish();
}

Response.Flush();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top