为啥以前在 iPad 上缓存时,SVG 中的图像并不总是从应用程序缓存中加载?

Posted

技术标签:

【中文标题】为啥以前在 iPad 上缓存时,SVG 中的图像并不总是从应用程序缓存中加载?【英文标题】:Why are images in SVGs not always loaded from the application cache when previously cached on the iPad?为什么以前在 iPad 上缓存时,SVG 中的图像并不总是从应用程序缓存中加载? 【发布时间】:2012-03-21 12:50:07 【问题描述】:

我们有一个允许用户查看 SVG 的网络应用程序。这些 SVG 通常包含使用相对 url 加载的图像。由于我们希望这是一个 iPad 的“网络应用程序”,我们还希望将其添加到 iPad 用户的主屏幕,并由 html 5 应用程序缓存对其进行缓存,以便用户可以离线查看这些 SVG 和相关图像。

当我们的应用程序从 iPad 主页图标加载时,应用程序缓存清单被正确读取,并且所有引用的资源都被缓存。当用户开始离线使用应用程序时,就会出现此问题。在应用程序的使用过程中,会在页面 DOM 中添加和删除 SVG。在此期间,SVG 中的某些图像无法从应用程序缓存中加载,即使它们确实存在并已缓存。相反,向服务器发出了对图像的请求,这显然失败了,因为用户不再在线。

有趣的是,在 iPad 上导航到 safari 中的页面时,似乎不会出现此问题。它似乎是特定于全页 Web 应用程序视图,但我不能保证。

我可以使用这个 HTML 页面很容易地重现这个:

<!DOCTYPE html>
<html manifest="testfiles.manifest">
<head>
    <title>Test</title>

    <script src="javascript/jquery-1.7.1.js" type="text/javascript"></script>

    <!-- Remove the browser chrome when the page is loaded from a homescreen icon -->
    <meta name="apple-mobile-web-app-capable" content="yes" />

</head>
    <body>

        <h1>Simple SVG caching test</h1>

        <h2>Basket ball SVG</h2>

        <p>
            <span id="remove">Remove</span> | <span id="add">Add</span>
        </p>

        <p>
            <span id="show">Show</span> | <span id="hide">Hide</span>
        </p>

        <p>
            <span id="reload">Reload</span>
        </p>

        <embed width='360' height='510' src='TestFiles/Basketball.svg' />

        <script type="text/javascript">
            $(function ()
            
                $("#remove").click(function ()
                
                    $("embed").remove();
                );

                $("#add").click(function ()
                
                    $("<embed width='360' height='510' src='TestFiles/Basketball.svg' />").appendTo("body");
                );

                $("#show").click(function ()
                
                    $("embed").show();
                );

                $("#hide").click(function ()
                
                    $("embed").hide();
                );

                $("#reload").click(function ()
                
                    location.reload(true);
                );

            )
        </script>

    </body>
</html>

这个 SVG:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg

   xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   
   >

  <image
     
     
     xlink:href="Basketball.png"
     x="0"
     y="0" />

</svg>

此图像被 SVG 引用:

还有这个清单文件:

CACHE MANIFEST
CACHE:
TestFiles/Basketball.svg
TestFiles/Basketball.png
Javascript/jquery-1.7.1.js

并按照以下步骤操作:

    打开 safari 并导航到复制 html 文件的位置(我们将其托管在 Windows 2008 / IIS 服务器上) 使用“添加到主屏幕”按钮将页面添加到主屏幕。 关闭 safari 并清理 safari 缓存 从新添加的书签加载页面 等待页面完全缓存。通常大约 5-10 秒,但您可以附加到一些应用程序缓存事件以注销进度。 关闭 wifi(或您使用的任何连接方式) 从新添加的书签加载页面 请注意,页面看起来已正确缓存。使用添加和删除按钮。当您使用页面上的“添加”按钮进行添加时,您应该很快注意到这一点。 SVG 中的图像资源并不总是从应用程序缓存中加载,即使它已被明确缓存。

当问题发生时,您应该会看到类似于以下屏幕截图的内容

我已经检查了一些明显的东西:

应用程序缓存清单具有正确的 mime 类型 清单已下载 清单中引用的资源已正确缓存

我的问题是:

有人知道为什么会这样吗? 是否有解决此问题的方法?

我已将此记录为苹果的错误,因此我将根据我可能从他们那里获得的任何反馈更新此问题!

谢谢!

安迪。

【问题讨论】:

ios 主页应用程序是否仍然使用与 iOS Safari 不同的 WebKit 版本,或者他们是否解决了这个问题?至于解决方法:JS 和/或 HTML 缓存是否正确?您能否将图像编码为数据 URL? 嘿,感谢您的建议,JS 和 HTML 都正确缓存,只是 HTML 页面上 SVG 内的图像未从应用程序缓存中检索。关于 iOS 主页应用程序和 iOS safari,我其实不知道。我猜他们使用的版本略有不同,或者他们之间有什么不同,但我不知道是什么。有什么办法可以找出来(我不是一个庞大的 iOS 专业人士!)。我们希望尽可能避免使用数据 URL,因为如果我们有多个 SVG 具有相同的图像(可能是背景或标题),这将是低效的。 其实想一想,能不能从请求的headers中获取webkit版本?...有时间我得看看! 有一些old detection scripts here,不知道在 iPad 上的表现如何。 看起来 web kit 版本是一样的,但是如果你比较用户代理字符串,全屏视图会错过最后的 'safari/xxxxx' 位。我想可能是因为它使用 UIWebView 组件而不是“Safari”应用程序?猜猜这一定是两者的区别。 【参考方案1】:

只是一个小小的“抬头”!如果您正在考虑这个问题,就像我一个小时前一样......:

清单文件区分大小写。

我有一个设计用于台式机、平板电脑和智能手机的网站。在 android (4.0.3) 上,我注意到在启用 HTML 5 App Cache 后,我的 SVG 图标开始失败,就像上面的情况一样。当用户刷新页面(并尝试从缓存中获取图标)时,它们显示为断开的链接。

我在文件夹名称中写了一个字母到我的 SVG 图标的错误大小写,修复此问题立即解决了问题。

【讨论】:

这不是问题,我可以告诉缓存清单是正确的,因为如果情况错误,它根本不会被缓存(我过去也经历过这种情况)。我的情况表明 SVG 中的图像被缓存,但并不总是从缓存中获取。如果我将所有 SVG 内联而不是嵌入,它也可以完美运行。估计是embed标签的bug吧。 另外,缓存清单是以编程方式创建的,所以这种情况确实应该是正确的! :)

以上是关于为啥以前在 iPad 上缓存时,SVG 中的图像并不总是从应用程序缓存中加载?的主要内容,如果未能解决你的问题,请参考以下文章

除非缓存,否则 SVG 图像不会在智能手机上加载

为啥在 PimCore v6.3.6 中不呈现 svg 预览?

为啥标签栏项目图标不在 iPad 设备的中心?

在 ipad 上水平显示 UIScrollview 中的图像并在点击时获取图像标签

为啥 iPad 默认启动图像方向不起作用(iOS 5)?

为啥我的 Mobile Safari 缓存不会清除?