【问题标题】:Why am I getting "Cannot access a closed Stream" here?为什么我在这里收到“无法访问关闭的流”?
【发布时间】:2016-07-11 02:50:04
【问题描述】:

堆栈跟踪看起来像

[ObjectDisposedException:无法访问已关闭的流。]
System.IO.__Error.StreamIsClosed() +53
System.IO.MemoryStream.Read(字节 [] 缓冲区,Int32 偏移量,Int32 计数) +11411219 System.Web.Mvc.FileStreamResult.WriteFile(HttpResponseBase 响应) +81 System.Web.Mvc.FileResult.ExecuteResult(ControllerContext 上下文) +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, doc, 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, doc, msHtml, msCss);
                        }
                    }
                    doc.Close();
                }
            }
            bytes = ms.ToArray();
            ms.Position = 0;
            return File(ms, "application/pdf", "Test.pdf");
        }
        catch
        {
            ms.Dispose();
            throw;
        }           
    }

【问题讨论】:

  • 因为一旦您退出操作方法,流就被关闭了。当视图试图访问它时,它发现它已经被关闭了。
  • Still not working with - 定义not working。此外,您还有一个名为 bytes 的变量,它不执行任何操作,但我很好奇在您的方法退出之前此数组中是否有任何内容。
  • 为什么将流内容复制到字节数组中?如果您这样做,则没有理由返回带有File(..),只需返回字节数组,例如File(bytes...)

标签: c# asp.net .net asp.net-mvc itextsharp


【解决方案1】:

一旦您退出操作方法,或者更确切地说,using ( var ms = new MemoryStream() ) { 块,流就关闭了。

您不需要处置 MemoryStream。 File(ms, "application/pdf", "Test.pdf"); 返回的 FileStreamResult 对象将是 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);
    }
}

你可以用 :

替换这个 using 块
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;
}

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

更新

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

【讨论】:

  • 您可能还想在将内存流中的位置传递给 File 之前重置它。 ms.Position=0;
  • 还有什么我可能会遗漏的吗?我将在上面粘贴我的更新代码
  • @SubparWebDev 你是什么意思?您是否遇到了其他问题?
【解决方案2】:

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

接下来,您应该不要在此处的MemoryStream 上使用using,因为FileStreamResult 操作结果将负责在发送流后处理流。现在,在发送发生之前,流实际上已关闭(通过处置)。

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

您可以将整个部分包装在 try...catch 中,以便在出现错误的情况下处理流(但 GC 最终会处理它,如果 sully 管理,MemoryStream 会处理它,所以这不是强制性的)。

【讨论】:

  • DocumentiTextSharp.Text.Document
  • PdfWriter 类可能正在关闭您的流。确保将 CloseStream 属性设置为 false。最重要的一行:)
猜你喜欢
  • 2019-09-09
  • 2020-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多