通过缓存获取带有 HTML 回退的图像?



我有一个用户图像控件,一个标识图标 - 如果用户设置了图像,它应该显示它,如果没有,它会显示带有彩色背景(和其他一些 HTML(的首字母缩写。

有大量这样的图像,一次显示很多,而且同一个用户可能会在一个页面上加载多次。图像可以包含 Alpha 透明度,并根据多种不同的背景颜色显示。图像可以是高 DPI,回退(以及它们旁边显示的大多数其他图像(使用 SVG。

图像可以更改,但不经常更改。通常,它们可以缓存几天或几周。

我认为有两种方法:

  • JavaScript
    在这个模型中,服务器返回我在IndexedDB中缓存的 JSON,并且 JSON 包含图像的数据 URI(如果已设置(。需要额外的 JS 来检查是否已为同一用户发出请求并避免重复该请求。

  • HTML<object>回退
    为此,服务器返回实际的图像字节,如果未找到,则返回 404。然后,如果未找到图像,则呈现<object>标记的内容:

#identicon,
#identicon > div { display: inline-block; width: 50px; height: 50px; line-height: 50px; text-align: center; background-color: red; overflow: hidden; }
<object id="identicon" data="api/users/joebloggs/photo" type="image/png">
<div>JB</div>
<!-- some more HTML and SVG content, snipped here -->
</object>
<object id="identicon" data="http://placehold.it/50" type="image/png">
<div>PH</div>
<!-- some more HTML and SVG content, snipped here -->
</object>

JS选项有明显的缺点,因为即使JS经过了大量优化IndexedDB也意味着回调(或同步选项,如LocalStorage,往往很慢(。这涉及相当多的JS,这应该是一个相当简单的任务。它有一个很大的优势 - 它只要求每个用户的照片一次。

我喜欢<object>回退的简单性,它有一些小缺点(许多奇怪的规则适用于对象内部的HTML呈现方式(,但一个主要问题:如果找不到图像,它每次都会再次往返服务器。很多用户没有图像。每个页面加载都会获得一长堆 404 的用户图像,它应该已经知道没有。

  1. JS是最好的方法,坚持下去 - 有什么方法可以减少JS/开销吗?
  2. <object>留给 404。
  3. <object>添加一个事件,当它无法加载图像时触发一些 JS,但我不确定如何在不恢复到 (1( 的情况下再次尝试停止它
  4. 更改服务器响应以返回用户映像,即使它失败也是如此。
    这失去了回退的优雅性,意味着大量服务器生成的图像。
    这就是SO/gravatar所做的,但对于高DPI屏幕的我们来说意味着一些问题。
  5. 更改服务器响应以在失败时返回透明图像。
    这意味着相同的图像被缓存很多次,即使对于有照片的用户,也意味着分层内容。它还会导致具有 Alpha 透明度的图像出现问题。
  6. 调整服务工作进程以将用户图像请求作为特殊情况处理,缓存 404 响应,并在再次尝试时跳过网络往返。
  7. 滥用其他一些 HTTP 状态响应,<object>仍然将其视为无法找到图像并回退到内容,但该内容由浏览器缓存。
  8. 其他方式?

所有这些都涉及妥协,但我也相当确定我在这里重新发明了轮子 - 很可能有人(在所有已经存在的 identicon 实现中(已经解决了这个问题。谁能为我指出正确的方向或建议解决问题的最佳方法?

您可以使用带有 404 的cache-control标头,浏览器将遵循它,并且此检查比调用localStorageIndexedDB要快得多。

解决方案只是将缓存标头添加到 404 响应中。在 .NET Core 中,这是:

context.Response.StatusCode = (int)HttpStatusCode.NotFound;
context.Response.Headers.Add("Cache-Control", $"public,max-age={duration}");

然后,它不会返回到服务器,直到持续时间到期,即使未找到图像,<object>仍会回退到其内容,并且<img>仍会触发error事件。

相关内容

  • 没有找到相关文章

最新更新