【问题标题】:How do I keep a stream open from model to controller?如何保持从模型到控制器的流打开?
【发布时间】:2012-06-07 18:55:19
【问题描述】:

我正在编辑 pdf,然后在新选项卡中打印。我收到一条错误消息,提示我“无法访问已关闭的流”。这就是我迄今为止所拥有的......

控制器

public ActionResult QST(string ID) 
{   
    ...
    PdfReader reader = new PdfReader(Server.MapPath("~/Content/PDF/QST.pdf"));
    QstRepository repo = new QstRepository();
    Stream newPdf = repo.GS(ID, reader);            
    return new FileStreamResult(newPdf, "application/pdf");
}

型号

public Stream GS(string ID, PdfReader reader)
{
    Stream newPdf = new MemoryStream();
    using (MemoryStream ms = new MemoryStream())
    {
        PdfStamper formFiller = new PdfStamper(reader, ms);
        AcroFields formFields = formFiller.AcroFields;
        formFields.SetField("ID", ID);

        formFiller.FormFlattening = true;
        formFiller.Writer.CloseStream = false;
        newPdf = ms;
        formFiller.Close();
    }
    return newPdf;
}

如何在关闭之前访问 pdf... 或者如何在关闭之后访问 pdf?

【问题讨论】:

    标签: c# asp.net-mvc pdf


    【解决方案1】:

    返回之前的最后两行代码是

    newPdf = ms;
    formFiller.Close(); 
    

    由于您的代码都在 using (MemoryStream ms = new MemoryStream()) 块内,MemoryStream 毫秒将在您返回之前关闭。

    由于您将newPdf 分配给变量ms,nwePdf 最终会返回ms 指向的相同(已关闭)MemoryStream

    您可以让public Stream GS(string ID, PdfReader reader) 只创建没有 using 块的流,但是如果代码中发生异常,您将面临保持打开状态的风险。我想您可以尝试以下方法:

    // All calls to GS() must ensure that the returned stream gets closed.
    public Stream GS(string ID, PdfReader reader) 
    { 
        MemoryStream newPdf = new MemoryStream();
        PdfStamper formFiller = null;
        try 
        { 
            formFiller = new PdfStamper(reader, newPdf); 
            AcroFields formFields = formFiller.AcroFields; 
            formFields.SetField("ID", ID); 
    
            formFiller.FormFlattening = true;
            //formFiller.Writer.CloseStream = false;
        }
        catch
        {
            // Only close newPdf on an exception
            newPdf.Close();
            throw; // Rethrow original exception
        }
        finally
        {
            // Always ensure that formFiller gets closed
            formFiller.Close();
        }
        return newPdf; 
    } 
    

    更新:我删除了额外的 MemoryStream,因为它只是在函数的开头声明,然后在末尾设置为指向另一个,而没有用于任何事情其他介于两者之间。

    更新:我找到了example using the PdfStamper。根据示例,调用 formFiller.Close() 是实际写入流的内容。在他们的示例中,他们没有将 Writer.CloseStream 属性设置为 false。这可能就是您得到空白页的原因。不幸的是,我无法在 PdfStamper 上找到任何实际文档来验证这一点。

    【讨论】:

    • 我认为我正在取得进展。我没有错误,现在我只有一个空白的新标签...
    • 我发现一篇文章表明有人正在做你想做的事。在他们的示例中,他们没有将 formFiller.Writer.CloseStream 设置为 false。试试看。
    【解决方案2】:

    在您的代码中,msnewPdf 指的是同一个 MemoryStream 实例;因为msusing 块的末尾关闭,所以newPdf 也被关闭(因为它是同一个流)。所以你需要在不关闭它的情况下返回Stream

    public Stream GS(string ID, PdfReader reader)
    {
        PdfStamper formFiller = new PdfStamper(reader, ms);
        AcroFields formFields = formFiller.AcroFields;
        formFields.SetField("ID", ID);
    
        formFiller.FormFlattening = true;
        formFiller.Writer.CloseStream = false;
        formFiller.Close();
        return ms;
    }
    

    我对 ASP.NET MVC 不是很熟悉,但我认为 FileStreamResult 负责关闭流。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-25
      • 2016-01-25
      • 2014-04-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多