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()
之前。但我不确定这不会使问题变得更糟,而且我很难进行测试(因为,一旦您下载了文件一次,就不会再次抛出错误)。
这可以解决问题吗?我的标题有问题吗?或者我还应该对 Response / PdfStamper 对象做其他事情吗?
In an ASP.NET application, I'm using iTextSharp (PdfStamper, mostly) to fill in some content on a PDF and send it to the user. The following code is inside an OnClick event:
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();
So, basically, PdfReader gets the file, PdfStamper takes the PdfReader as an argument, and will push its finished PDF to Response.OutputStream.
The problem is that, with IE and Adobe Reader, if you select "Open" from the file dialog, Adobe Reader throws an error saying "file could not be found". Users can "Save" the file just fine, and even starting the download again (clicking "Open" again when asked) seems to work. But on a new machine that's never downloaded the file, Adobe Reader seems to misplace the file between it going to the Temporary Files or whatever IE does.
I can only imagine one thing right now: Response.End()
, should, maybe, be Response.Close()
instead, or maybe the whole thing should have Response.Flush()
before it. But I don't know for sure that that won't make the problem worse, and I'm having a hard time testing (because, once you've downloaded the file once, the error isn't thrown again).
Might that fix the problem? Do I have something wrong in the headers? Or is there something else I should be doing with the Response / PdfStamper objects?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
每当我向用户强制提供内容时,我都会遵循这组响应步骤:
这似乎可以很好地防止所有“找不到文件”垃圾。
编辑:对于那些对这些标头的实际含义感兴趣的人:
Pragma: public
有助于控制缓存以向后兼容 HTTP/1.0 请求。即使已经有缓存的响应,它也确保您的请求能够到达服务器。Expires: 0
是响应过期之前的时间间隔(以秒为单位)。设置为 0 会使响应立即过期,有助于避免缓存过时。Cache-control: Must-revalidate
告诉缓存它必须服从您的每个命令(即当您请求时它必须给您一个新的响应)。Cache-control: post-check=0, pre-check=0
:这是一个以秒为单位的时间间隔,必须在(分别)提供内容之前/之后检查响应的新鲜度。设置为 0 会强制立即检查响应的新鲜度。 (更多信息请访问 MSDN.)Whenever I force content at a user, I follow this set of steps for the Response:
This seems to be pretty good at preventing all the "file not found" garbage.
EDIT: For those interested in what these headers actually mean:
Pragma: public
helps control cache for backwards compatibility with HTTP/1.0 requests. It ensures that your request makes it to the server even if there's already a cached response.Expires: 0
is an interval in seconds after which the response expires. Setting to 0 expires the response immediately, helping avoid a stale cache.Cache-control: must-revalidate
tells the cache that it must obey your every command (i.e. it must give you a new response when you ask for it).Cache-control: post-check=0, pre-check=0
: this is an interval in seconds that a response must be checked for freshness after/prior to (respectively) being served the content. Setting to 0 forces freshness of the response to be checked immediately. (More at MSDN.)