59 votes

Diffusion de fichiers volumineux vers ASP.NET MVC

Pour une application que je suis en train de travailler, j'ai besoin de permettre à l'utilisateur d'envoyer des fichiers très volumineux--c'est à dire, potentiellement plusieurs giga-octets--par l'intermédiaire de notre site web. Malheureusement, ASP.NET MVC apparaît à la charge de l'ensemble de la requête dans la RAM avant de commencer le service, il-n'est pas exactement idéal pour une telle application. Notamment, en essayant de contourner le problème via le code comme suit:

if (request.Method == "POST")
{
    request.ContentLength = clientRequest.InputStream.Length;
    var rgbBody = new byte[32768];

    using (var requestStream = request.GetRequestStream())
    {
        int cbRead;
        while ((cbRead = clientRequest.InputStream.Read(rgbBody, 0, rgbBody.Length)) > 0)
        {
            fileStream.Write(rgbBody, 0, cbRead);
        }
    }
}

ne parvient pas à contourner le tampon-la-demande-en-RAM mentalité. Est-il un moyen facile de contourner ce problème?

25voto

Benjamin Pollack Points 10458

Il s'avère que mon code initial était fondamentalement correct; le seul changement requis était de changer

 request.ContentLength = clientRequest.InputStream.Length;
 

à

 request.ContentLength = clientRequest.ContentLength;
 

Le premier flux dans toute la demande pour déterminer la longueur du contenu; ce dernier vérifie simplement l'en-tête Content-Length , ce qui nécessite uniquement que les en-têtes aient été envoyés dans leur intégralité. Cela permet à IIS de commencer à diffuser la requête presque immédiatement, ce qui élimine complètement le problème initial.

17voto

RedFilter Points 84190

Bien sûr, vous pouvez le faire. Voir RESTful les uploads de fichier avec HttpWebRequest et IHttpHandler. J'ai été en utilisant cette méthode depuis quelques années et avoir un site qui a été testé avec des fichiers de plusieurs gigaoctets. Essentiellement, vous voulez créer votre propre IHttpHandler, ce qui est plus facile qu'il n'y paraît.

En un mot, vous créez une classe qui implémente l'IHttpHandler l'interface, ce qui signifie que vous avez à l'appui de la IsReusable de la propriété et de la méthode ProcessRequest. En plus de cela, il y a un petit changement à votre site web.config, et il fonctionne comme un charme. À ce stade dans le cycle de vie de la demande, la totalité du fichier en cours de téléchargement ne pas se charger en mémoire, donc il parfaitement étapes autour des problèmes de mémoire insuffisante.

Notez que dans le web.config,

<httpHandlers>
 <add verb="*" path="DocumentUploadService.upl" validate="false" type="TestUploadService.FileUploadHandler, TestUploadService"/>
</httpHandlers>

le fichier référencé, DocumentUploadService.lup, n'existe pas réellement. C'est juste là pour donner une autre extension, de sorte que la demande n'est pas intercepté par la norme gestionnaire. Vous pointez votre formulaire de téléchargement de fichier de ce chemin, mais alors votre FileUploadHandler classe de coups de pied dans les reçoit effectivement le fichier.

Mise à jour: en Fait, le code que j'utilise est différente de celle de l'article, et je pense que je suis tombé sur la raison pour laquelle il travaille. J'utilise le HttpPostedFile catégorie, dans laquelle "les Fichiers sont téléchargés dans le MIME multipart/form-data format. Par défaut, toutes les demandes, y compris les champs de formulaire et les fichiers téléchargés, plus de 256 KO sont mises en mémoire tampon sur le disque, plutôt que tenu dans la mémoire du serveur."

if (context.Request.Files.Count > 0)
{
    string tempFile = context.Request.PhysicalApplicationPath;
    for(int i = 0; i < context.Request.Files.Count; i++)
    {
        HttpPostedFile uploadFile = context.Request.Files[i];
        if (uploadFile.ContentLength > 0)
        {
            uploadFile.SaveAs(string.Format("{0}{1}{2}",
              tempFile,"Upload\\", uploadFile.FileName));
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X