C# 如何保持从模型到控制器的流是开放的?
我正在编辑pdf,然后在新选项卡中打印。我得到一个错误,说我“无法访问一个封闭的流”。这是我到目前为止 控制器C# 如何保持从模型到控制器的流是开放的?,c#,asp.net-mvc,pdf,C#,Asp.net Mvc,Pdf,我正在编辑pdf,然后在新选项卡中打印。我得到一个错误,说我“无法访问一个封闭的流”。这是我到目前为止 控制器 public ActionResult QST(string ID) { ... PdfReader reader = new PdfReader(Server.MapPath("~/Content/PDF/QST.pdf")); QstRepository repo = new QstRepository(); Stream newPdf =
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");
}
模型
如何在pdf关闭之前访问它。。。或者如何在返回后访问pdf?返回前的最后两行代码是
newPdf = ms;
formFiller.Close();
由于您的代码都在使用(MemoryStream ms=new MemoryStream())
块的中,因此在您返回之前,MemoryStream
ms将被关闭
由于将newPdf
赋值给变量ms
,nwePdf最终返回ms
指向的相同(已关闭的)MemoryStream
您可以使用公共流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,因为在函数开始时只声明了一个,然后在函数结束时设置为指向另一个,而不用于其间的任何其他内容
更新:我找到了一个。根据该示例,调用formFiller.Close()实际上是写入流的操作。在他们的示例中,他们没有将Writer.CloseStream属性设置为false。这可能就是为什么你会得到一张空白页。不幸的是,我无法找到任何关于PdfStamper的实际文档来验证这一点。返回前的最后两行代码是
newPdf = ms;
formFiller.Close();
由于您的代码都在使用(MemoryStream ms=new MemoryStream())
块的中,因此在您返回之前,MemoryStream
ms将被关闭
由于将newPdf
赋值给变量ms
,nwePdf最终返回ms
指向的相同(已关闭的)MemoryStream
您可以使用公共流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,因为在函数开始时只声明了一个,然后在函数结束时设置为指向另一个,而不用于其间的任何其他内容
更新:我找到了一个。根据该示例,调用formFiller.Close()实际上是写入流的操作。在他们的示例中,他们没有将Writer.CloseStream属性设置为false。这可能就是为什么你会得到一张空白页。不幸的是,我无法找到任何关于PdfStamper的实际文档来验证这一点。在您的代码中,ms
和newPdf
引用了相同的MemoryStream
实例;由于ms
在使用
块结束时关闭,newPdf
也关闭(因为它是相同的流)。因此,您需要返回流
,而不关闭它:
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
负责关闭流。在您的代码中,ms
和newPdf
引用相同的MemoryStream
实例;由于ms
在使用
块结束时关闭,newPdf
也关闭(因为它是相同的流)。因此,您需要返回流
,而不关闭它:
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
负责关闭流。我认为我正在取得进展。我没有错误,现在我只有一个空白的新标签…我发现一篇文章,显示某人正在做你正试图做的事情。在他们的示例中,他们没有将formFiller.Writer.CloseStream
设置为false。试试看,我想我正在进步。我没有错误,现在我只有一个空白的新标签…我发现一篇文章,显示某人正在做你正试图做的事情。在他们的示例中,他们没有将formFiller.Writer.CloseStream
设置为false。试试看。