流式传输PDF失败-未找到文件



今天早上我花了一些时间试图帮助一个同事解决一个奇怪的bug,目前我们三个人都被这个bug难住了。这个场景是我们有一个正在开发的系统,它允许用户将pdf文件附加到数据记录。系统使用服务从服务器存储和检索文件,并在附件表中存储标识符,以指示哪些文件属于哪些记录。

然后,在应用程序的两个不同页面上,我们有一个网格,它显示记录的附件列表。网格中的链接按钮允许用户打开给定的附件。链接按钮引发一个命令事件,该事件传递附件的标识符作为其参数。在命令事件处理程序中,我们从参数中获取标识符,使用它以字节数组的形式从服务中检索附件,然后覆盖响应对象以返回附件。下面是代码:

byte[] byteFile = DataHandler.GetAttachmentDocument(selectedAttachmentID);
if (DataHandler.sErrorMsg != "")
{//Error trying to retrieve file...
    this.DisplayMessageBox(DataHandler.sErrorMsg);
}
else
{//File retrieved...
    Response.Clear();
    Response.Buffer = true;
    Response.ContentType = "application/pdf";
    Response.AddHeader("content-disposition", "attachment;filename=" + lblAttachmentName.Text);
    Response.Charset = "";
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
    Response.BinaryWrite(byteFile);
    Response.Flush();
    Response.Close();
    Response.End();
}

现在这个完全相同的代码在一个页面上完美地工作,而在另一个页面上失败了。在这两种情况下,当单击按钮并显示下载对话框时,单击打开按钮并打开adobe reader窗口。在工作页上,阅读器窗口显示请求的文档,但在另一个页面上,我们从阅读器窗口得到一个错误,上面写着:There was an error opening this document. This file cannot be found.在调试器中,我们可以逐步执行,看到我们在byteFile中获得相同的字节数,并且我们正在逐步执行完整的方法,没有错误。

我们在谷歌上搜索了很多,并尝试了这段代码的几个变体,但没有任何运气。我知道我们尝试了几件事,将内容类型更改为八位字节流,将内容长度添加到标题中,将缓冲区更改为false,删除内容处置属性。唯一一个明显的区别是删除了内容处理属性,在这种情况下,文档显示在原始窗口中,而不是单独的adobe reader窗口中。另一个被提出但尚未尝试的想法是,将网格和相关逻辑提取到一个web控件中,然后可以在两个页面上重用。还有其他建议吗?

不要使用Response.Close()和Response.End()。Flush()就足够了

原因如下:http://blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation.aspx

虽然我们无法确定是什么导致了这个问题,但我们确定它至少在某种程度上是特定于用户/机器的。因此,我们最好的猜测是客户端出现了某种奇怪的冲突或缓存问题。

我们最终做的工作是开发一个空白页面,它接受查询字符串上的附件ID和名称,执行一些安全检查,然后返回所请求的附件。这为我们提供了一个包含附件检索代码的可重用模块。

然后我们进入提供附件的页面,并将我们的网格模板从带有命令参数的链接按钮更改为带有导航URL绑定到新页面路径+查询字符串参数和_blank目标的超链接。

最终的结果是我们消除了错误,而没有对页面结构进行重大更改,保持了期望的最终用户体验,并且拥有更易于维护的代码结构。

感谢Leon的提示。虽然它没有解决问题,但它确实帮助我们清理了代码。

最新更新