在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对象做些什么呢?
答案 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()
这似乎很好地防止了所有“找不到文件”的垃圾。
编辑:对于那些对这些标题实际含义感兴趣的人:
Pragma: public
有助于控制缓存以实现与HTTP / 1.0请求的向后兼容性。即使已经有缓存的响应,它也可以确保您的请求进入服务器。Expires: 0
是响应到期后的间隔(以秒为单位)。设置为0会立即使响应失效,从而有助于避免过时的缓存。 Cache-control: must-revalidate
告诉缓存它必须服从你的每个命令(即当你要求它时它必须给你一个新的响应。)Cache-control: post-check=0, pre-check=0
:这是一个以秒为单位的间隔,必须在(分别)提供内容之后/之前检查响应的新鲜度。设置为0会强制立即检查响应的新鲜度。 (More at MSDN。)