如何保持从模型到控制器的流打开

本文关键字:控制器 何保持 模型 | 更新日期: 2023-09-27 18:36:27

>我正在编辑一个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?

如何保持从模型到控制器的流打开

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

newPdf = ms;
formFiller.Close(); 

由于您的代码都在using (MemoryStream ms = new MemoryStream())块中,因此无论如何,MemoryStream ms都将在您返回之前关闭。

由于您将newPdf分配给变量ms,nwePdf finalualy 返回与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,因为一个只是在函数的开头声明,然后在末尾设置为指向另一个,而从未用于两者之间的任何其他内容。

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

在你的代码中,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;
}

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