Why am I getting "Can't access private stream" here?

Stack trace looks like

[ObjectDisposedException: Unable to access the private stream.]
System.IO .__ Error.StreamIsClosed () +53
System.IO.MemoryStream.Read (buffer [], Int32 offset, Int32 count) +11411219 System.Web.Mvc.FileStreamResult.WriteFile (HttpResponseBase response) +81 System.Web.Mvc.FileResult.ExecuteResult (ControllerContext context) +168
System.Web.Mvc.ControllerActionInvoker.InvokeActionResult (ControllerContext controllerContext, ActionResult actionResult) +13

after calling

//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"); } 

I read MemoryStream - I can’t access the private stream , but this is not the same scenario because I do not use StreamReader

Edit: Still not working with

  [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; } } 
+6
source share
2 answers

The thread was closed as soon as you left the action method, or rather, in the using ( var ms = new MemoryStream() ) { block.

You do not need to allocate a MemoryStream. FileStreamResult object returned by File(ms, "application/pdf", "Test.pdf"); will delete it after rendering . Code that actually sends stream data:

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

You can replace this block with:

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

to ensure that the thread will be deleted if an error occurs.

UPDATE

As Igor noted, and, as the source code shows, FileStreamResult will not be reset by the position of the stream. You will need to set the value to 0 before calling return File(...)

+6
source

The PdfWriter class can close your stream. Be sure to set the CloseStream property to false.

Further, you should not use using in MemoryStream here, since the result of the FileStreamResult action will take care of the utilization of the stream after it is sent. Right now, the stream is actually closed (by order) before the transfer takes place.

Also, before sending the file, you should look for the stream back to position 0.

You can wrap the entire part in try...catch , however, to get rid of the thread in case of an error (but the GC will eventually take care of this and the MemoryStream if sully control, so this is not necessary).

0
source

All Articles