为什么我在这里“无法访问封闭的流”?

堆栈跟踪看起来像

[ObjectDisposedException:无法访问已关闭的Stream。]
System.IO .__ Error.StreamIsClosed()+ 53
System.IO.MemoryStream.Read(Byte [] 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

在调用之后

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

This is some sample text!!!

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

我读过MemoryStream – 无法访问封闭的Stream ,但这不是同一个场景,因为我没有使用StreamReader

编辑:仍然没有使用

  [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 = @"

This is some sample text!!!

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

退出操作方法后,流即关闭,或者更确切地说, using ( var ms = new MemoryStream() ) { block。

您不需要处理MemoryStream。 File(ms, "application/pdf", "Test.pdf");返回的FileStreamResult对象File(ms, "application/pdf", "Test.pdf"); 将在渲染后处理它 。 实际发送流数据的代码是:

 protected async override Task WriteFileAsync(HttpResponse response) { var outputStream = response.Body; using (FileStream) { var bufferingFeature = response.HttpContext.Features.Get(); bufferingFeature?.DisableResponseBuffering(); await FileStream.CopyToAsync(outputStream, BufferSize); } } 

您可以使用以下块替换此块:

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

确保在发生错误时处理流。

UPDATE

正如Igor所提到的,并且正如源代码所示,FileStreamResult不会重置流位置。 在调用return File(...)之前,你必须将它设置为0

PdfWriter类可能正在关闭您的流。 确保将CloseStream属性设置为false。

接下来你不应该在这里using MemoryStream ,因为FileStreamResult操作结果将在发送它之后处理流。 现在,在发送之前,流实际上已关闭(通过dispose)。

此外,您应该在发送文件之前将流回寻到位置0。

您可以将整个部分包装在try...catch但是如果出现错误则处理流(但是GC最终会处理它而MemoryStream如果被管理,那么这不是强制性的)。