C# · 12月 22, 2021

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

堆栈跟踪看起来像

[ObjectDisposedException: Cannot access a closed 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 = @”<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,msHtml,msCss); } } doc.Close(); } } //bytes = ms.ToArray(); return File(ms,”application/pdf”,”Test.pdf”); }

我读过MemoryStream – Cannot access a closed 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 = @”<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,msCss); } } doc.Close(); } } bytes = ms.ToArray(); ms.Position = 0; return File(ms,”Test.pdf”); } catch { ms.Dispose(); throw; } }解决方法 退出操作方法后,流即关闭,或者更确切地说,使用(var ms = new MemoryStream()){block.

您不需要处理MemoryStream. File返回的FileStreamResult对象(ms,“application / pdf”,“Test.pdf”);将dispose it after rendering.实际发送流数据的代码是:

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

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

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

确保在发生错误时丢弃流.

UPDATE

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