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

在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() . 但我不会让问题变得更糟,而且我已经下载了一次文件,错误不再被抛出了 .

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

回答(1)

2 years ago

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

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()

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

EDIT: 对于那些对这些 Headers 实际意味着什么感兴趣的人:

  • Pragma: public 有助于控制缓存以实现与HTTP / 1.0请求的向后兼容性 . 即使已经有缓存的响应,它也可以确保您的请求进入服务器 .

  • Expires: 0 是响应到期后的间隔(秒) . 设置为0会立即使响应失效,从而有助于避免过时的缓存 .

  • Cache-control: must-revalidate 告诉缓存它必须服从你的每个命令(即当你要求它时它必须给你一个新的响应) .

  • Cache-control: post-check=0, pre-check=0 :这是一个以秒为单位的间隔,必须在(分别)提供内容之后/之前检查响应的新鲜度 . 设置为0会强制立即检查响应的新鲜度 . (More at MSDN . )

  • 其余部分只是描述您希望用户接收的内容 . 指定"attachment"告诉浏览器将文件作为下载提供,并且不以内联方式显示它 .