2010-04-02 4 views
23

Je fais des tests avec ASP.NET HttpHandler pour télécharger un fichier écrit directement sur le flux de réponse, et je ne suis pas sûr de la façon dont je le fais. Ceci est un exemple de procédé, dans l'avenir, le fichier pourrait être stocké dans un blob dans la base de données:Quelques questions à propos de l'écriture sur le flux de réponse ASP.NET

 public void GetFile(HttpResponse response) 
    { 
     String fileName = "example.iso"; 
     response.ClearHeaders(); 
     response.ClearContent(); 
     response.ContentType = "application/octet-stream"; 
     response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName); 
     using (FileStream fs = new FileStream(Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data"), fileName), FileMode.Open)) 
     { 
      Byte[] buffer = new Byte[4096]; 
      Int32 readed = 0; 

      while ((readed = fs.Read(buffer, 0, buffer.Length)) > 0) 
      { 
       response.OutputStream.Write(buffer, 0, readed); 
       response.Flush(); 
      } 
     } 
    } 

Mais, je ne sais pas si cela est correct ou il y a une meilleure façon de le faire. Mes questions sont les suivantes:

  1. Quand j'ouvre l'URL avec le navigateur, affiche la boîte de dialogue « Enregistrer le fichier » ... mais il semble que le serveur a déjà commencé à pousser des données dans le flux avant que je clique sur « Enregistrer ", est-ce normal?
  2. Si je supprime la ligne "response.Flush()", quand j'ouvre l'url avec le navigateur, ... je vois comment le serveur web pousse les données mais le dialogue "Save File" n'apparaît pas, (ou du moins pas dans un délai raisonnable) pourquoi?
  3. Lorsque j'ouvre l'URL avec un objet WebRequest, je vois que HttpResponse.ContentLength est "-1", bien que je puisse lire le flux et obtenir le fichier. Quelle est la signification de -1? Quand HttpResponse.ContentLength va afficher la longueur de la réponse? Par exemple, j'ai une méthode qui récupère un grand xml compressé avec deflate comme un flux binaire, mais dans ce cas ... quand j'y accède avec un WebRequest, dans le HttpResponse je peux réellement voir le ContentLength avec la longueur du flux , Pourquoi?
  4. Quelle est la longueur optimale pour le tableau Byte [] que j'utilise comme tampon pour des performances optimales dans un serveur Web? J'ai lu que c'est entre 4K et 8K ... mais quels facteurs dois-je considérer pour prendre la bonne décision.
  5. Est-ce que cette méthode gonfle l'utilisation de IIS ou de la mémoire client? ou est-ce qu'il tamponne effectivement le transfert correctement?

Désolé pour tant de questions, je suis assez nouveau dans le développement web: P

Vive.

+1

Vous devriez aussi jeter un coup d'œil aux implémentations de Boilerplate HttpHandler ici (http://haacked.com/archive/2005/03/17/AnAbstractBoilerplateHttpHandler.aspx) et ici (http://www.hanselman.com /blog/PermaLink,guid,5c59d662-b250-4eb2-96e4-f274295bd52e.aspx). – R0MANARMY

+0

Votre façon d'apprendre est appréciée. Continue . –

+0

Cela fonctionne: [http://stackoverflow.com/questions/3362849/outofmemoryexception-when-send-big-file-500mb-using-filestream-aspnet][1] [ 1]: http://stackoverflow.com/questions/3362849/outofmemoryexception-when-send-big-file-500mb-using-filestream-aspnet –

Répondre

16
  1. Oui; c'est normal.
  2. Si vous ne videz jamais, le navigateur n'obtient aucune réponse jusqu'à la fin du serever (même pas l'en-tête Content-Disposition). Par conséquent, il ne sait pas afficher une boîte de dialogue de fichier.
  3. L'en-tête Content-Length est défini uniquement si la réponse entière est mise en mémoire tampon (si vous ne videz jamais) ou si vous la définissez vous-même. Dans ce cas, vous pouvez et devez le régler vous-même; écrire

    response.AppendHeader("Content-Length", new FileInfo(path).Length.ToString()); 
    
  4. Je recommande 4K; Je n'ai pas de base solide pour la recommandation.
  5. Cette méthode est la meilleure façon de le faire. En appelant Flush à l'intérieur de la boucle, vous envoyez immédiatement la réponse sur le réseau, sans aucune mise en mémoire tampon. Cependant, pour des performances accrues, vous pouvez utiliser la compression GZIP.
+0

Merci à tous, vous avez dissipé tous mes doutes. Je suis content d'avoir rejoint cette communauté: D – vtortola

2
  1. Oui, il s'agit d'un tampon. Flush pousse le contenu mis en cache vers le navigateur. Si elle n'est jamais poussée, vous n'obtiendrez pas de boîte de dialogue de sauvegarde.
  2. Difficile à dire sans voir les fichiers/URL/flux que vous utilisez.
  3. Je pense que les facteurs dépendent de la lenteur de votre page. Vous aurez une meilleure performance vers 4k. Et peut-être, la valeur la plus basse sera mieux adaptée aux connexions plus lentes.
  4. Voir # 1 & 2.
+0

Merci à tous, vous effacez tous mes doutes. Je suis content d'avoir rejoint cette communauté: D – vtortola

2

Pour # 3 vous devez définir l'en-tête de longueur de contenu dans votre http-réponse. Beaucoup de ces valeurs proviennent des en-têtes http. Je crois que vous pouvez changer le tampon en changeant une propriété de mise en mémoire tampon sur l'objet de réponse à faux. Je ne l'ai pas fait depuis un moment donc je ne me souviens pas de ce que ça pourrait être.

+0

Merci à tous, vous avez dissipé tous mes doutes. Je suis content d'avoir rejoint cette communauté: D – vtortola

Questions connexes