【发布时间】:2012-03-03 07:00:32
【问题描述】:
背景
我正在尝试帮助一位同事调试过去 6 个月内没有出现的问题。在最近部署 ASP.NET MVC 2 应用程序后,FileResult 强制用户打开或保存 PDF 文件的响应在客户端计算机上存在足够长的时间以供 PDF 阅读器打开它们时遇到问题。
IE 的早期版本(尤其是 6)是唯一受影响的浏览器。 Firefox 和 Chrome 以及更新版本的 IE (>8) 都按预期运行。考虑到这一点,下一部分定义了重新创建问题所需的操作。
行为
- 用户单击指向操作方法的链接(带有
href属性的普通超链接)。 - action 方法生成一个表示为字节流的 PDF。 always 方法重新创建 PDF。
-
在 action 方法中,设置了 headers 来指示浏览器如何缓存响应。它们是:
response.AddHeader("Cache-Control", "public, must-revalidate, post-check=0, pre-check=0"); response.AddHeader("Pragma", "no-cache"); response.AddHeader("Expires", "0");对于那些不熟悉headers 所做的事情的人:
一个。 缓存控制:公共
表示响应可以被任何缓存缓存,即使它通常是不可缓存的或只能在非共享缓存中缓存。
b. 缓存控制:必须重新验证
当缓存接收到的响应中存在 must-revalidate 指令时,该缓存不能在条目变得陈旧后使用该条目来响应 后续请求,无需先使用源服务器重新验证它
c。 Cache-Control: pre-check(IE5引入)
以秒为单位定义一个时间间隔,在此之后必须检查实体的新鲜度。检查可能会在向用户显示资源后进行,但可确保在下一次往返中缓存的副本是最新的。
d。 Cache-Control: post-check(在 IE5 中引入)
以秒为单位定义一个时间间隔,在该时间间隔之后,必须在向用户显示资源之前检查实体的新鲜度。
e。 Pragma: no-cache(确保向后兼容 HTTP/1.0)
当请求消息中存在 no-cache 指令时,应用程序应该将请求转发给源服务器,即使它有正在请求的缓存副本
f。 过期
Expires 实体标头字段给出了响应被视为过时的日期/时间。
-
我们从动作中返回文件
return File(file, "mime/type", fileName); 向用户显示打开/保存对话框
- 单击“保存”按预期工作,但单击“打开”会启动 PDF 阅读器,但 IE 存储的临时文件在阅读器尝试打开文件时已被删除,因此它抱怨文件丢失(确实如此)。
这里有六个其他应用程序使用相同的标题强制 Excel、CSV、PDF、Word 和大量其他内容向用户展示,从来没有出现过问题。
问题
- 标题是否适合我们正在尝试执行的操作?我们希望文件暂时存在(被缓存),但总是被新版本替换,即使请求可能相同)。
在返回 FileResult 之前,在 action 方法中设置了响应标头。我已经要求我的同事尝试创建一个继承自 FileResult 的新类,并改为覆盖 ExecuteResult 方法,以便它修改标头,然后改为使用 base.ExecuteResult() - 对此没有任何状态。
我有一种预感,“0”的“Expires”标题是罪魁祸首。根据this W3C article,将其设置为“0”意味着“已经过期”。我确实希望它过期,我只是不希望 IE 在处理它的应用程序有机会打开它之前将其从文件系统中删除。
一如既往,谢谢!
编辑:解决方案
经过进一步测试(使用 Fiddler 检查标头),我们发现我们认为设置的响应标头不是浏览器正在解释的标头。由于我自己不熟悉代码,我不知道一个潜在的问题:标题在操作方法之外被踩到了。
不过,我将保留这个问题。仍然很突出的是:Expires 标头的值 0 与 -1 之间似乎存在一些差异。如果有人可以声称在设计上与 IE 存在差异,我仍然想听听。至于解决方案,在所有浏览器中将Expires 值设置为-1 时,上述标头确实可以正常工作。
更新 1
How to control web page caching, across all browsers? 的帖子详细描述了通过设置 Expires = 0 可以在所有浏览器中防止缓存。我仍然不赞成 0 与 -1 的论点...
【问题讨论】:
-
您可能想从这里使用
NoCacheAttribute:stackoverflow.com/questions/1160105/… -
@lasseespeholt:我确实希望浏览器缓存文件;我只是希望它立即过期,所以它总是被替换。根本不缓存它会是个问题。
标签: asp.net asp.net-mvc-2 iis caching http-headers