我正在开发一个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内容将完全更改为显示另一个带有fileupload组件的角度组件。
myImageController返回LastModified标头和cache-control:no-cache并且必须重新验证。
刷新后(点击F5),我的页面请求获取所有img src,这是正确的:如果图像已被修改,则会被下载,如果没有,我只需要304就可以了。
注意:我的图像作为blob字段存储在数据库中。
当我的页面内容使用包含img标签的单页应用程序动态重新加载时,浏览器不会调用GET http请求,而是立即从缓存中获取图像。我假设这是一个浏览器优化,以避免多次在同一页面上获取相同的资源。
第一个解决方案是添加类似?time =(new Date())。getTime()来生成唯一的URL并避免浏览器缓存。这不会在请求中发送If-Modified-Since标头,我会每次完整地下载我的图像。
进行“真实”刷新:角度应用中的第一页加载非常慢,我不会刷新所有内容。
为了简化问题,我尝试创建一个包含3个图像的静态html页面,其中包含与我的控制器完全相同的链接:/ myImageController / 1。使用chrome developper工具,我可以看到只调用一个get请求。如果我设法在这种情况下获得多个服务器调用,它可能会解决我的问题。
感谢您的帮助。
答案 0 :(得分:1)
5th version of HTML specification描述了这种行为。浏览器可以重用图像而不管缓存相关的HTTP头。有关详细信息,请查看此answer。您可能需要使用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撰写的New Tricks in XMLHttpRequest2文章,Nicholas C. Zakas撰写的Working with files in JavaScript, Part 4: Object URLs文章以及URL.createObjectURL() MDN page和Same-origin policy MDN page。
答案 1 :(得分:0)
您可以使用随机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失效。