我正在开发angular2应用程序(单页应用程序)。我的页面从不"重新加载",但它的内容会根据用户交互而变化。
我遇到了一些缓存问题,尤其是图像。
上下文:
我的页面包含一个可编辑的图像列表:
<ul>
<li><img src="myImageController/1"><a href="editPage/1">Edit</a></li>
<li><img src="myImageController/2"><a href="editPage/2">Edit</a></li>
<li><img src="myImageController/3"><a href="editPage/3">Edit</a></li>
</ul>
当我想编辑图像(编辑链接)时,我的dom内容会完全更改为显示另一个带有文件上传组件的角度组件。
myImageController返回LastModified标头和缓存控制:没有缓存,必须重新验证。
刷新后(点击F5),我的页面会请求获取所有img src,这是正确的:如果图像被修改,它就会被下载,如果没有,我只会得到一个304,这很好。
注意:我的图像以blob字段的形式存储在数据库中
问题:
当我的页面内容用包含img标记的单页应用程序动态重新加载时,浏览器不会调用GET http请求,而是立即从缓存中获取图像。我认为这是一种浏览器优化,以避免多次在同一页面上获得相同的资源。
错误的解决方案:
第一个解决方案是添加类似的内容?time=(new Date()).getTime()生成唯一的url并避免浏览器缓存。这不会在请求中发送If Modified Since标头,我每次都会完整地下载我的图像。
做一次"真正的"刷新:angular应用程序的第一页加载非常慢,我不想全部刷新。
测试
为了简化这个问题,我试图创建一个静态html页面,其中包含3个图像,它们与我的控制器具有完全相同的链接:/myImageController/1。使用chrome developer工具,我可以看到只调用了一个get请求。在这种情况下,如果我能够获得多个服务器调用,这可能会解决我的问题。
谢谢你的帮助。
XMLHttpRequest
和Blob。在这种情况下,您还需要考虑同源政策。
您可以使用以下功能来确保用户代理执行每个请求:
var downloadImage = function ( imgNode, url ) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "blob";
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200 || xhr.status == 304) {
var blobUrl = URL.createObjectURL(xhr.response);
imgNode.src = blobUrl;
// You can also use imgNode.onload callback to release blob resources.
setTimeout(function () {
URL.revokeObjectURL(blobUrl);
}, 1000);
}
}
};
xhr.send();
};
有关更多信息,请参阅Eric Bidelman的文章《XMLHttpRequest2中的新技巧》,《使用JavaScript中的文件》,第4部分:Nicholas C.Zakas的文章《对象URL》,以及URL.createObjectURL()MDN页面和同源策略MDN页面。
您可以使用随机ID技巧。这将更改URL,以便浏览器重新加载图像。这并不是说可以在查询参数中强制完全断开缓存,或者在哈希中允许浏览器重新验证缓存中的图像(并避免在未更改的情况下重新下载)。
function reloadWithCache(img: HTMLImageElement, url: string) {
img.src = url.replace(/#.*/, "") + "#" + Math.random();
}
function reloadBypassCache(img: HTMLImageElement, url: string) {
let sep = img.indexOf("?") == -1? "?" : "&";
img.src = url + sep + "nocache=" + Math.random()
}
请注意,如果您经常使用reloadBypassCache
,那么最好修复缓存头。此功能总是会影响您的原始服务器,从而导致更高的运行成本并使CDN无效。