Question

Je crée un service de téléchargement simple afin qu'un utilisateur puisse télécharger toutes ses images depuis son site. Pour ce faire, il suffit de tout compresser dans le flux http.

Cependant, il semble que tout soit stocké en mémoire et que les données ne soient pas envoyées avant la fin du fichier zip et la sortie. Je veux que le service commence à envoyer immédiatement, sans utiliser trop de mémoire.

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

Je peux voir la mémoire du processus de travail augmenter pendant la création du fichier, puis la libérer lorsque son envoi est terminé. Comment puis-je faire cela sans utiliser trop de mémoire?

Était-ce utile?

La solution

Désactiver la mise en mémoire tampon des réponses avec context.Response.BufferOutput = false; et supprimez l'appel Flush à la fin de votre code.

Autres conseils

use Response.BufferOutput = false; au début de ProcessRequest et vide la réponse après chaque fichier.

FYI. Ce code fonctionne pour ajouter de manière récursive une arborescence complète de fichiers, avec diffusion en continu sur le navigateur:

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();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top