由Adobe Reader丢失的Response.Stream输出(PDF)

时间:2010-02-24 17:57:57

标签: c# itextsharp response outputstream

在ASP.NET应用程序中,我使用iTextSharp(主要是PdfStamper)来填写PDF上的一些内容并将其发送给用户。以下代码位于OnClick事件中:

PdfReader r = new PdfReader(
  new RandomAccessFileOrArray(Request.MapPath(compatiblePdf)), null
);

ps = new PdfStamper(r, Response.OutputStream);
AcroFields af = ps.AcroFields;

af.SetField("ContactInfo[0]", o.mallName);
af.SetField("ClientName", string.Format("{0} {1}", c.firstName, c.lastName));
af.SetField("ClientEmail", c.emailAddress);
ps.FormFlattening = true;
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=Form.pdf");
ps.Close();
Response.End();

所以,基本上,PdfReader获取文件,PdfStamper将PdfReader作为参数,并将其完成的PDF推送到Response.OutputStream。

问题在于,使用IE和Adobe Reader,如果从文件对话框中选择“打开”,Adobe Reader会抛出错误提示“无法找到文件”。用户可以“保存”文件,甚至可以再次开始下载(在被问到时再次单击“打开”)似乎可以正常工作。但是在一台永远不会下载文件的新机器上,Adobe Reader似乎错误地将文件放在临时文件或IE之间的文件中。

我现在只能想象一件事:Response.End(),也许应该是Response.Close(),或者整个事情应该在它之前Response.Flush()。但我不确定这会不会使问题变得更糟,而且我很难测试(因为,一旦你下载了一次文件,就不会再次抛出错误了。)

可能解决问题吗?我在标题中有什么问题吗?或者我应该对Response / PdfStamper对象做些什么呢?

1 个答案:

答案 0 :(得分:5)

每当我强迫用户使用内容时,我都会按照以下步骤进行响应:

Response.Clear()
Response.ClearHeaders()
Response.Buffer = True
Response.ContentType = "your mime type"
Response.CacheControl = "public"
Response.AddHeader("Pragma", "public")
Response.AddHeader("Expires", "0")
Response.AddHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0")
Response.AddHeader("Content-Description", "Description of your content")
Response.AddHeader("Content-Disposition", "attachment; filename=""somefile.pdf""")

' Add your content to the buffer here

Response.Flush()
Response.End()

这似乎很好地防止了所有“找不到文件”的垃圾。

编辑:对于那些对这些标题实际含义感兴趣的人:

  1. Pragma: public有助于控制缓存以实现与HTTP / 1.0请求的向后兼容性。即使已经有缓存的响应,它也可以确保您的请求进入服务器。
  2. Expires: 0是响应到期后的间隔(以秒为单位)。设置为0会立即使响应失效,从而有助于避免过时的缓存。
  3. Cache-control: must-revalidate告诉缓存它必须服从你的每个命令(即当你要求它时它必须给你一个新的响应。)
  4. Cache-control: post-check=0, pre-check=0:这是一个以秒为单位的间隔,必须在(分别)提供内容之后/之前检查响应的新鲜度。设置为0会强制立即检查响应的新鲜度。 (More at MSDN。)
  5. 其余部分只是描述您希望用户接收的内容。指定“附件”会告诉浏览器将文件作为下载提供,并且不以内联方式显示。