为啥以前在 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 中的图像并不总是从应用程序缓存中加载?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 PimCore v6.3.6 中不呈现 svg 预览?