2016-03-23 3 views
6

trace de la pile ressemblePourquoi est-ce que je reçois "Impossible d'accéder à un flux fermé" ici?

[ObjectDisposedException: Impossible d'accéder à un flux fermé.]
System.IO .__ Error.StreamIsClosed() +53
System.IO.MemoryStream.Read (tampon octet [], int32 offset, compte int32) 11411219 System.Web.Mvc.FileStreamResult.WriteFile (réponse HttpResponseBase) 81 System.Web.Mvc.FileResult.ExecuteResult (contexte ControllerContext) 168
de System.Web.Mvc.ControllerActionInvoker. InvokeActionResult (ControllerContext controllerContext, ActionResult actionResult) +13

après avoir invoqué

 //Byte[] bytes; 
     using (var ms = new MemoryStream()) 
     { 
      using (var doc = new Document()) 
      { 
       using (var writer = PdfWriter.GetInstance(doc, ms)) 
       { 

        doc.Open(); 
        //var example_html = @"<p>This <em>is </em><span class=""headline"" style=""text-decoration: underline;"">some</span> <strong>sample <em> text</em></strong><span style=""color: red;"">!!!</span></p>"; 
        var example_html = System.IO.File.ReadAllText(Path.Combine(Server.MapPath("~/EmailTemplates"), "template.html")); 
        var example_css = @".headline{font-size:200%}"; 
        using (var srHtml = new StringReader(example_html)) 
        { 
         iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml); 
        } 
        using (var msCss = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_css))) 
        { 
         using (var msHtml = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_html))) 
         { 
          iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msHtml, msCss); 
         } 
        } 


        doc.Close(); 
       } 
      } 
      //bytes = ms.ToArray(); 
      return File(ms, "application/pdf", "Test.pdf"); 
     } 

J'ai lu MemoryStream - Cannot access a closed Stream, mais ce n'est pas le même scénario parce que je ne suis pas en utilisant StreamReader

Edit: ne fonctionne toujours pas avec

[OutputCache(NoStore = true, Duration = 0)] 
    public ActionResult Run() 
    { 
     Byte[] bytes; 
     var ms = new MemoryStream(); 
     try 
     { 
      using (var doc = new Document()) 
      { 
       using (var writer = PdfWriter.GetInstance(doc, ms)) 
       { 
        writer.CloseStream = false; 
        doc.Open(); 
        var example_html = @"<p>This <em>is </em><span class=""headline"" style=""text-decoration: underline;"">some</span> <strong>sample <em> text</em></strong><span style=""color: red;"">!!!</span></p>"; 
        //var example_html = System.IO.File.ReadAllText(Path.Combine(Server.MapPath("~/EmailTemplates"), "LinkEmailTemplate.html")); 
        var example_css = @".headline{font-size:200%}"; 
        using (var msCss = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_css))) 
        { 
         using (var msHtml = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_html))) 
         { 
          iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msHtml, msCss); 
         } 
        } 
        doc.Close(); 
       } 
      } 
      bytes = ms.ToArray(); 
      ms.Position = 0; 
      return File(ms, "application/pdf", "Test.pdf"); 
     } 
     catch 
     { 
      ms.Dispose(); 
      throw; 
     }   
    } 
+1

Parce que le flux a été fermé dès que vous avez quitté la méthode d'action. Lorsque la vue a essayé d'y accéder, elle a trouvé qu'elle était déjà fermée. –

+1

'Ne fonctionne toujours pas' - ne définit pas 'ne fonctionne pas'. Aussi vous avez une variable nommée 'bytes' qui ne fait rien mais je suis curieux de savoir s'il y a quoi que ce soit dans ce tableau avant que votre méthode ne se termine. – Igor

+2

* Pourquoi * copiez-vous le contenu du flux dans un tableau d'octets? Si vous faites cela, il n'y a pas de raison de retourner le * stream * avec 'File (..)', juste retourner le tableau d'octets par exemple 'File (bytes ...)' –

Répondre

0

La classe PdfWriter peut être en train de vous fermer r flux. Assurez-vous de définir la propriété CloseStream sur false.

Ensuite, vous devez pas utiliserusing sur le MemoryStream ici, puisque le résultat de l'action FileStreamResult prendra soin de disposer le flux après de l'envoyer. À l'heure actuelle, le flux est effectivement fermé (par disposition) avant l'envoi a lieu.

De même, vous devez rechercher le flux en position 0 avant d'envoyer le fichier.

Vous pouvez cependant envelopper la pièce entière dans un try...catch pour disposer du flux en cas d'erreur (mais le GC s'en chargera éventuellement et MemoryStream s'il est géré, donc ce n'est pas obligatoire).

+0

'Document' est' iTextSharp.Text.Document' –

6

Le flux a été fermé dès que vous avez quitté la méthode d'action, ou plutôt le bloc using (var ms = new MemoryStream()) {.

Vous n'avez pas besoin de disposer du MemoryStream. L'objet FileStreamResult renvoyé par File(ms, "application/pdf", "Test.pdf"); sera dispose it after rendering. Le code qui envoie effectivement les données de flux est:

protected async override Task WriteFileAsync(HttpResponse response) 
{ 
    var outputStream = response.Body; 

    using (FileStream) 
    { 
     var bufferingFeature = response.HttpContext.Features.Get<IHttpBufferingFeature>(); 
     bufferingFeature?.DisableResponseBuffering(); 

     await FileStream.CopyToAsync(outputStream, BufferSize); 
    } 
} 

Vous pouvez remplacer ce bloc à l'aide de:

var ms = new MemoryStream(); 
try 
{ 
    //.. 
    //From Igor's comment. FileStreamResult won't reset the stream position itself 
    ms.Position=0; 
    return File(ms, "application/pdf", "Test.pdf"); 
} 
catch 
{ 
    ms.Dispose(); 
    throw; 
} 

pour faire en sorte que le flux s'éliminés si une erreur se produit.

MISE À JOUR

Comme Igor mentionné, et que le code source montre, FileStreamResult ne réinitialise pas la position de flux. Vous devrez le mettre à 0 avant d'appeler return File(...)

+1

Vous souhaitez probablement également réinitialiser la position dans le flux de mémoire avant de le transmettre à Fichier. 'ms.Position = 0;' – Igor

+0

Merci, mis à jour –

+0

Y at-il autre chose que je pourrais manquer? Je vais coller mon code de mise à jour ci-dessus –