5

我正在开发一个使用 HTML5 的小型单页应用程序。一个功能是显示嵌入在页面中的 PDF 文档,可以从列表中选择哪些文档。

现在我正在尝试让 Chrome(首先,然后是所有其他现代浏览器)使用本地客户端缓存来完成对 PDF 文档的简单 GET 请求,而无需通过服务器(当然第一次除外)。<object>我通过在 HTML 中的元素上设置“数据”属性来请求 PDF 文件。

我找到了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)]

在我的控制器上。对该控制器的第一个请求 - 带有 URLhttp://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:*

对相同 URL 的第三次请求会导致另一个往返和带有以下标头的 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>或者,当我通过在元素上设置“数据”属性来显示 PDF 时,我是否做得不对?

4

2 回答 2

1

客户端从来没有义务缓存。每个浏览器都可以自由地使用自己的启发式方法来决定是否值得缓存一个对象。毕竟,缓存的任何使用都会与缓存的其他用途“竞争”。

缓存并非旨在保证快速响应;平均而言,它旨在增加经常使用的不变资源已经存在的可能性。您正在尝试做的不是缓存旨在提供帮助的内容。

根据您报告的结果,您在 2012 年使用的 Chrome 版本认为缓存将在 60 秒后过期且仅被请求一次的对象是没有意义的。所以它在使用后丢弃了第一个副本。然后你第二次询问,它开始给这个 URL 更高的优先级——它一定记住了最近的 URL,并观察到这是第二个请求——它把副本保存在缓存中,但是当第三个请求到来时,要求服务器验证它是否仍然有效(可能是因为到期时间只有几秒钟)。服务器说“304 - 未修改 - 使用您缓存的副本”。它没有再次发送pdf。

恕我直言,对于即将过期的对象,这是合理的缓存行为。


如果您想增加 PDF 保留更长时间的机会,请给出更晚的到期时间,但说它必须与服务器检查以查看它是否仍然有效。

如果使用 HTTP Cache-Control 标头,这可能是: private, max-age: 3600, must-revalidate. 这样,您应该会看到到服务器的往返,只要页面有效,它将给出 304 响应。这应该是一个快速响应,因为没有数据被发回——使用浏览器的缓存版本。

private是可选的——与这种缓存行为无关——我假设无论这个易失的 PDF 是什么,它只对给定的用户有意义和/或不应该在某个共享位置长时间闲逛。


如果您真的需要完全不与服务器对话的性能,那么请考虑编写 javascript 来隐藏/显示包含该 PDF 的 DOM 元素,而不是删除它,并且需要再次请求它。

您的页面 javascript 代码是唯一“理解”您真正希望 PDF 保留的地方,即使您当前没有向用户展示它。

于 2014-08-15T22:56:20.903 回答
0

您是否尝试过将 OutputCache 的 Location 属性设置为“Client”

[OutputCache(Duration=60, Location = OutputCacheLocation.Client)]

默认情况下,位置属性设置为“任何”,这可能意味着响应缓存在客户端、代理或服务器上。

MSDN 输出缓存位置的更多信息

于 2013-03-07T06:15:16.683 回答