我正在使用HTML5开发一个小型单页面应用程序。一个功能是显示嵌入在页面中的PDF文档,可以从列表中选择哪些文档。
我是否正在尝试制作Chrome(首先,然后是所有其他现代浏览器)使用本地客户端缓存来完成对PDF文档的简单GET请求,而无需通过服务器(当然不是第一次) 。我通过在HTML中的<object>
元素上设置“data”属性来请求PDF文件。
我找到了working example for XMLHttpRequest(不是<object>
)。如果您使用Chrome的开发者工具(网络标签),您会看到第一个请求发送到服务器,并导致对这些标头的响应:
Cache-Control:public,Public
Content-Encoding:gzip
Content-Length:130
Content-Type:text/plain; charset=utf-8
Date:Tue, 03 Jul 2012 20:34:15 GMT
Expires:Tue, 03 Jul 2012 20:35:15 GMT
Last-Modified:Tue, 03 Jul 2012 20:34:15 GMT
Server:Microsoft-IIS/7.5
Vary:Accept-Encoding
第二个请求是从本地缓存提供的,没有任何服务器往返,这就是我想要的。
回到我自己的应用程序中,然后我使用ASP-NET MVC 4并设置
[OutputCache(Duration=60)]
在我的控制器上。对此控制器的第一个请求 - 使用网址http://localhost:63035/?doi=10.1155/2007/98732
会产生以下标头:
Cache-Control:public, max-age=60, s-maxage=0
Content-Length:238727
Content-Type:application/pdf
Date:Tue, 03 Jul 2012 20:45:08 GMT
Expires:Tue, 03 Jul 2012 20:46:06 GMT
Last-Modified:Tue, 03 Jul 2012 20:45:06 GMT
Server:Microsoft-IIS/8.0
Vary:*
第二个请求导致另一个到服务器的往返,响应更快(建议服务器端缓存?)但返回200 OK和这些标题:
Cache-Control:public, max-age=53, s-maxage=0
Content-Length:238727
Content-Type:application/pdf
Date:Tue, 03 Jul 2012 20:45:13 GMT
Expires:Tue, 03 Jul 2012 20:46:06 GMT
Last-Modified:Tue, 03 Jul 2012 20:45:06 GMT
Server:Microsoft-IIS/8.0
Vary:*
对同一网址的第三个请求会导致另一个往返和带有这些标头的304响应:
Cache-Control:public, max-age=33, s-maxage=0
Date:Tue, 03 Jul 2012 20:45:33 GMT
Expires:Tue, 03 Jul 2012 20:46:06 GMT
Last-Modified:Tue, 03 Jul 2012 20:45:06 GMT
Server:Microsoft-IIS/8.0
Vary:*
我的问题是,如何设置OutputCache属性以获得所需的行为(即在初始请求的X秒内从客户端缓存中填写的PDF请求)?
或者,当我通过在<object>
元素上设置“data”属性来显示PDF时,我做得不对吗?
答案 0 :(得分:1)
客户从不义务进行缓存。每个浏览器都可以自由使用它自己的启发式来决定是否值得缓存一个对象。毕竟,任何使用缓存都会与缓存的其他用途“竞争”。
缓存并非旨在保证快速响应;平均而言,它旨在增加经常使用的不会改变的资源的可能性。 您要做的不是缓存的目的是什么。
根据您报告的结果,您在2012年使用的Chrome版本认为缓存一个将在60秒后过期的对象毫无意义,并且只被要求过一次。所以它在使用之后扔掉了第一个副本。然后你第二次问了,它开始给这个URL更优先 - 它必须记住最近的URL,并观察到这是第二个请求 - 它将副本保存在缓存中,但是当第三个请求来了,要求服务器验证它仍然有效(大概是因为到期时间只有几秒钟)。服务器说“304 - 未修改 - 使用你缓存的副本”。它没有再发送pdf。
对于即将到期的对象,恕我直言,这是合理的缓存行为。
如果您希望增加PDF更长时间停留的可能性,请提供更晚的到期时间,但要说它必须与服务器核实是否仍然有效。< / p>
如果使用HTTP Cache-Control标头,则可能是:private, max-age: 3600, must-revalidate
。有了这个,您应该看到服务器的往返,只要页面有效,就会给出304响应。这应该是一个快速响应,因为没有发回数据 - 使用浏览器的缓存版本。
private
是可选的 - 与此缓存行为无关 - 我假设这个易变的PDF是什么,它只对给定的用户有意义和/或不应该长时间闲逛时间,在一些共享的位置。
如果你真的需要不与服务器交谈的性能,那么考虑编写javascript来隐藏/显示持有该PDF的DOM元素,而不是丢弃它,并且需要请求再一次。
您的页面javascript代码是唯一一个“理解”您真正希望PDF保留的地方,即使您当前没有向用户展示它。
答案 1 :(得分:0)
您是否尝试将OutputCache的Location属性设置为“Client”
[OutputCache(Duration=60, Location = OutputCacheLocation.Client)]
默认情况下,location属性设置为“Any”,这可能意味着响应缓存在客户端,代理服务器或服务器上。