使用缓存获取带有HTML后备的图像?

时间:2017-08-03 07:04:01

标签: javascript html css httpresponse html-object

我有一个用户图像控件,一个identicon - 如果用户有一个图像集应该显示它,如果没有它显示带有彩色背景的首字母(以及其他一些HTML)。

这些图片数量众多,一次显示批次,同一用户可能会在页面上多次加载。图像可以包含Alpha透明度,并针对多种不同的背景颜色显示。图像可以是高DPI,并且后备(以及它们旁边显示的大多数其他图像)都使用SVG。

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

我认为有两种解决方法:

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

  • HTML <object>后备
    为此,服务器返回实际的图像字节,如果没有找到,则返回404。然后,如果找不到图像,#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>
IndexedDB

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

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

  1. JS是最好的方法,坚持下去 - 任何方式都可以减少JS /开销?
  2. <object>留给404。
  3. <object>添加一个事件,当它无法加载图像时触发某些JS,但我不知道如何在不恢复为(1)
  4. 的情况下再次尝试停止它
  5. 更改服务器响应以返回用户图像,即使它失败也是如此 这会失去后备的优雅,并意味着许多服务器生成的图像 这就是SO / gravatar所做的事情,但对于具有高DPI屏幕的我们来说意味着一些问题。
  6. 更改服务器响应以在失败时返回透明图像 这意味着相同的图像被缓存很多次,并且意味着即使对于拥有照片的用户也可以分层内容。它还会导致带有Alpha透明度的图像出现问题。
  7. 根据特殊情况调整服务工作者处理用户图像请求,如果再次尝试,则缓存404响应并跳过网络往返。
  8. 滥用其他一些HTTP状态响应, compile 'com.google.android.exoplayer:exoplayer:r2.4.4' compile 'com.google.android.exoplayer:exoplayer-core:r2.4.4' compile 'com.google.android.exoplayer:exoplayer-dash:r2.4.4' compile 'com.google.android.exoplayer:exoplayer-ui:r2.4.4' private ExoPlayer exoPlayer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); exoPlayer = ExoPlayer.Factory.newInstance(2); } 仍然认为无法找到图像并回退到内容,但浏览器会缓存这种状态。
  9. 其他一些方式?
  10. 所有这些都涉及妥协,但我也相当确定我在这里重新发明了轮子 - 很可能是某人(在已经存在的所有identicon实现中)已经解决了这个问题。任何人都可以指出我正确的方向或建议解决问题的最佳方法吗?

1 个答案:

答案 0 :(得分:0)

您可以使用带有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事件。