Trace de pile ressemble à
[ObjectDisposedException: impossible d'accéder à un flux fermé.]
System.IO .__ Error.StreamIsClosed () +53
System.IO.MemoryStream.Read (tampon Byte [], décalage Int32, compte Int32) +11411219 System.Web.Mvc.FileStreamResult.WriteFile (réponse HttpResponseBase) +81 System.Web.Mvc.FileResult.ExecuteResult (contexte ControllerContext) +168
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 - Impossible d'accéder à un flux fermé , mais ce n'est pas le même scénario car je n'utilise pas 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;
}
}
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 jeter le MemoryStream. L'objet FileStreamResult renvoyé par File(ms, "application/pdf", "Test.pdf");
sera le disposera après le rendu . Le code qui envoie les données du flux est le suivant:
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 en utilisant:
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 s'assurer que le flux est éliminé en cas d'erreur.
METTRE &AGRAVE; JOUR
Comme Igor l'a mentionné, et comme le code source l'indique, FileStreamResult ne réinitialise pas la position du flux. Vous devrez le mettre à 0 avant d'appeler return File(...)
La classe PdfWriter
ferme peut-être votre flux. Assurez-vous de définir la propriété CloseStream
sur false.
Ensuite, vous devriez non utiliser using
sur la MemoryStream
ici, car le résultat de l'action FileStreamResult
permettra de supprimer le flux après l'avoir envoyé. Actuellement, le flux est effectivement fermé (par disposition) avant que l’envoi ait lieu.
Vous devez également rechercher le flux en position 0 avant d’envoyer le fichier.
Vous pouvez toutefois insérer la totalité de la pièce dans un try...catch
afin d'éliminer le flux en cas d'erreur (mais le GC s'en occupera éventuellement et MemoryStream
s'il est géré, ce n'est donc pas obligatoire).