0

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

4

2 回答 2

3

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

newPdf = ms;
formFiller.Close(); 

由于您的代码都在一个using (MemoryStream ms = new MemoryStream())块内,因此MemoryStreamms 将在您返回之前关闭。

由于您要分配newPdf给变量ms,因此 nwePdf 最终会返回指向的相同(已经关闭MemoryStreamms

您可以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 上找到任何实际文档来验证这一点。

于 2012-06-07T18:59:32.090 回答
1

在您的代码中,msnewPdf引用相同的MemoryStream实例;因为在块ms的末尾关闭,所以也关闭(因为它是同一个流)。所以你需要返回而不关闭它:usingnewPdfStream

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负责关闭流。

于 2012-06-07T19:00:28.343 回答