今天早上我花了一些时间试图帮助一位同事犯了一个奇怪的错误,目前我们三个人都难倒了。方案是我们正在开发一个允许用户将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阅读器窗口。到目前为止提出但尚未尝试的另一个想法是将网格和相关逻辑提取到Web控件,然后可以在两个页面上重用。还有其他建议吗?
答案 0 :(得分:1)
不要使用Response.Close()和Response.End()。 Flush()就足够了。
答案 1 :(得分:0)
虽然我们无法确切地确定导致问题的原因,但我们确定它至少在某种程度上是用户/机器特定的。所以我们最好的猜测是在客户端出现某种奇怪的冲突或缓存问题。
我们最终做的工作是开发一个空白页面,它接受查询字符串上的附件ID和名称,执行一些安全检查,然后返回请求的附件。这给了我们一个可重复使用的模块,其中包含我们的附件检索代码。
然后我们进入提供附件的页面,并将网格模板从带有命令参数的链接按钮更改为超链接,其中导航URL绑定到新页面的路径+查询字符串参数,目标为{{ 1}}。
最终结果是我们在不对页面结构进行重大更改的情况下消除了错误,保持了所需的最终用户体验,并且具有更易于维护的代码结构。
感谢Leon提示。虽然它没有解决问题,但确实帮助我们清理了一些代码。