Chrome不会在SVG中缓存图片

时间:2013-10-17 08:42:28

标签: javascript google-chrome svg browser-cache cache-control

我刚刚发现,如果他们的cache-control标头设置为no-cache,则Chrome不会缓存放置在SVG中的图像。 Firefox& IE10似乎忽略了这个设置。

我用静态SVG创建了一个小测试页面:

HTML:

<div style="width: 500px; text-align: center;">
    <input id="move-left-btn" type="button" value="&lt;&lt;">
    <input id="move-right-btn" type="button" value="&gt;&gt;">
</div>

<div class="svgwrapper" style="width: 500px; height: 250px; background-color: lightgrey;">
    <svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" width="500" height="250">
        <g id="svggroup" class="transition-on" transform="matrix(0.2,0,0,0.2,80,35)">
            <image width="1672" height="887" opacity="1" xlink:href="https://dl.dropboxusercontent.com/sh/q7htlj5h8qqfhjf/SVDuynM7R3/car.png"></image>
        </g>
    </svg>
</div>

使用Javascript:

$(document).ready(function() {
    var curXPos = 80;

    // Local test function which represent some server calls in my "real life" scenario
    // Just updates the x-position in the transform matrix in this test case
    function updateSvgText(svgText, posXDelta) {
        curXPos += posXDelta;
        if (curXPos < 0) {
            curXPos = 160;
        } else if (curXPos > 160) {
            curXPos = 0;
        }

        return svgText.replace(/matrix\(.*\)/, 'matrix(0.2,0,0,0.2,' + curXPos + ',35)');
    }

    // Fetch the new SVG (in real life from server) and rerender it
    function moveSvg(posXDelta) {
        var svg = $('#svg'),
            svgText = updateSvgText($('.svgwrapper').html(), posXDelta);

        svg.empty();
        svg.append($(svgText).children());
    }

    $('#move-left-btn').click($.proxy(moveSvg, this, -20));
    $('#move-right-btn').click($.proxy(moveSvg, this, 20));
});
  • 将源图像的cache-control标题设置为no-cache的工作示例(每次按下“移动”按钮后,在Chrome中闪烁):
    http://jsfiddle.net/zF6NF/4/

  • cache-control标题设置为max-age=315360000,public(不闪烁)的不同源图像的相同示例:
    http://jsfiddle.net/zF6NF/5/

在Chrome中,您可以在第一个示例中看到每个按钮上的图像重新加载(图像的“闪烁”以及开发工具的网络选项卡中可见),而Firefox在两个示例中都顺利地重新呈现SVG而没有任何重装。

其他一些信息:

  1. 这只是一个例子。在我的“真实场景”中,我从服务器收到一个新的SVG(而不是updateSvgText方法调用),这意味着我不能通过改变变换的值来执行SVG的部分更新矩阵属性,但每次都必须重新渲染整个SVG(至少现在......)。

  2. 我无法控制图像的来源,这意味着两件事:

    • 我无法更改cache-control标题
    • 我无法创建Base64编码的数据-uris,在本地保存它们只是在渲染之前用这些数据uris替换SVG内的图像(由于“相同的资源来源”策略,无法创建Base64编码的数据uri ...)
  3. 有没有办法......

    • 即使图像来自不受控制的远程位置,也会在本地覆盖/否决cache-control标题?
    • 从另一个域加载的Image中创建Base64编码数据-ri,我对客户端没有任何控制权?
    • 告诉Chrome总是将图像缓存在我的SVG中?

    毋庸置疑,其他解决方案也非常受欢迎!

    由于

1 个答案:

答案 0 :(得分:2)

不幸的是,当涉及到缓存时,它是服务器工作的99%。

In-dept指南:here

浏览器将始终根据特定条件查找文件的更新版本:

  • 缓存条目没有到期日期,并且首次在浏览器会话中访问内容
  • 缓存条目的截止日期已过期
  • Cache-Control / Pragma告诉浏览器不要缓存
  • 标题中的Etag是一种痛苦。

就解决方案而言:

  • 非常坚持要求您的服务器人员进行缓存 (删除etag,Cache-Control:public,max-age = 31536000,Pragma:public)
  • 在您的域上创建一个代理,该代理需要来自网站的图像(可选地转换为base64),然后发送到您的客户端(使用正确的标头)。以下是PHP的示例:here