我正在编辑pdf,然后在新标签页中打印。我收到一条错误消息,说我“无法访问封闭的流”。这就是我到目前为止......
CONTROLLER
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");
}
MODEL
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?
答案 0 :(得分:3)
返回前代码的最后两行是
newPdf = ms;
formFiller.Close();
由于您的代码全部位于using (MemoryStream ms = new MemoryStream())
块内,因此MemoryStream
ms将在您返回之前关闭。
由于您要将newPdf
分配给变量ms
,因此nwePdf eventualy会返回MemoryStream
指向的相同(已关闭)ms
。
您可以public Stream GS(string ID, PdfReader reader)
只创建没有使用块的流,但如果您的代码中出现异常,则会冒着保持打开状态的风险。我想你可以尝试以下方法:
// 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上找到任何实际文档来验证这一点。
答案 1 :(得分:1)
在您的代码中,ms
和newPdf
引用相同的MemoryStream
个实例;由于ms
在using
块结束时关闭,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
负责关闭流。