Chrome无法缓存SVG内部的图像

9

我刚刚发现如果SVG中的图片的缓存控制头设置为no-cache,Chrome不会缓存它们。而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));
});

在Chrome中,您可以看到第一个示例中每次按下按钮时图像重新加载(在开发工具的网络选项卡中可见),而Firefox在两个示例中都平滑地重新渲染SVG,而无需任何重新加载。

一些额外的信息:

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

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

    • 我无法更改cache-control
    • 我无法创建Base64编码的数据URI,将其保存在本地,并在渲染之前将SVG中的图像替换为那些数据URI(由于“相同资源来源”政策,无法创建Base64编码的数据URI...)

是否有任何方式可以...

  • 即使图像来自不受控制的远程位置,也可以在本地覆盖/覆盖cache-control头吗?
  • 从客户端没有任何控制的不同域加载的图像中创建Base64编码的数据URI?
  • 以某种方式告诉Chrome始终缓存我的SVG内部的图像?

不用说其他解决方案也非常欢迎!

谢谢


无关的评论 - 如果文本中后面还有另一个括号,则正则表达式可能会过度匹配。因此应该是/matrix\([^)]*\)或类似的东西。 - Sanjay Manohar
1个回答

3

遗憾的是,当涉及到缓存时,99%的工作是由服务器来完成的。

深入指南:此处

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

  • 缓存条目没有过期日期,并且在浏览器会话中首次访问内容
  • 缓存条目具有过期日期,但已经过期
  • Cache-Control/Pragma告诉浏览器不要缓存
  • 标头中的Etag很麻烦。

解决方案包括:

  • 向服务器团队强调您需要缓存(删除etag,Cache-Control:public,max-age=31536000,Pragma:public)
  • 在您的域上创建一个代理,从站点获取图像(可选转换为base64),然后将其发送到客户端(具有正确的标头)。这里是PHP的示例:此处

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接