img HTML标记不尊重HTTP刷新标头(但在浏览器中加载图像URL)

Pau*_*ine 6 html django image nginx http-headers

我正在使用HTTP Refresh标头提供占位符图像,如下所示:

Connection:keep-alive
Content-Type:image/gif
Date:Thu, 01 Aug 2013 14:16:25 GMT
Refresh:10; url=/media/thumbs/document/18.png
Server:nginx/1.4.1
Transfer-Encoding:chunked
Run Code Online (Sandbox Code Playgroud)

如果我在完整窗口中加载图像占位符URL,则内容会在10秒后刷新,但如果我在图像标记src属性中放置相同的URL ,则图像永远不会刷新(在Chrome和FF中测试).

我为什么要这样做?我有一个应用程序,其中文档的缩略图需要几秒钟由服务器生成(这是一个复杂的SVG渲染).当用户在创建新文档后立即转到文档列表时,缩略图可能还没有.我试图使用带有刷新标题的占位符图像在几秒钟后加载真实的缩略图.

我不记得是怎么回事,但是在Netscape浏览器过去的好时光,像刷新标题这样的东西有时我们是如何破解动画的(甚至在Flash之前 - 我是史前还是什么?).我们称之为"服务器推送"(我猜这个流行语是用Comet模型回收的).

我在客户端使用Angular.js(服务器端是Django + uWSGI + Nginx),所以使用javascript攻击东西应该很容易,但我很好奇:是否有任何技巧(没有javascript)图像标签在几秒钟后加载另一个源?

(我也会标记这个Django和Nginx,因为可能有人知道服务器端解决方案)

Lou*_*cci 1

解释

当您直接在浏览器中打开图像时,它会被打包为 HTML 文档。

转到 google 最新的 doodle jpg,然后打开 HTML 控制台 ( http://www.google.com/logos/doodles/2013/erwin_schrdingers_126th_birthday-2002007-hp.jpg )。

在 Chrome 中您将得到:

<html><body style="margin: 0px;">
<img style="-webkit-user-select: none" src="http://www.google.com/logos/doodles/2013/erwin_schrdingers_126th_birthday-2002007-hp.jpg">
</body></html>
Run Code Online (Sandbox Code Playgroud)

对于文档内部的 IMG 标记 src,不会进行这种“包装”。

解决方案

如果您打算仅使用 HTTP 标头,那么您将陷入 @JamesHolderness 描述的 multipart/x-mixed-replace,但请注意,像这样保持 HTTP 连接保持打开状态可能会损害您的服务器性能,并可能使您面临 DDoS 攻击。

我打算建议使用 CSS 动画/过渡来延迟加载图像。不幸的是,只有 Chrome 支持背景图像(CSS 属性)动画。另一个选项是 display: none,因为在显示元素之前图像不会加载,但没有浏览器支持在显示上进行动画或转换(CSS 属性)。

这是仅 Chrome、仅 CSS 的解决方案http://jsfiddle.net/r2Tag/

超文本标记语言

<div id="thumbnail"></div>
Run Code Online (Sandbox Code Playgroud)

CSS

#thumbnail {
    position: relative;
    width: 475px;
    height: 184px;
    background-image:url('http://lh3.ggpht.com/Z9Bl8P_zqvnB_FPBw5PqZlHelALdwWoBV5EZSEVI85kS698xDzghSmLzREcaS1Uh31L5PIRdAiuMUcBSNlBGCsc-9YshQaxnMA4uzU2c-Q');
    animation: loadthumbnail 0s linear 10s;
    -webkit-animation: loadthumbnail 0s linear 10s;
    animation-fill-mode: forwards;
    -webkit-animation-fill-mode: forwards;
}
@keyframes loadthumbnail { to {
    width: 491px;
    height: 190px;
    background-image:url('https://www.google.com/logos/doodles/2013/erwin_schrdingers_126th_birthday-2002007-hp.jpg');
} }
@-webkit-keyframes loadthumbnail { to {
    width: 491px;
    height: 190px;
    background-image:url('https://www.google.com/logos/doodles/2013/erwin_schrdingers_126th_birthday-2002007-hp.jpg');
} }
Run Code Online (Sandbox Code Playgroud)

编辑如果您使用数据 URI SVG 作为动画背景图像,则可以绕过 Chrome 的解析器预加载图像。

SVG 示例

<svg x="0px" y="0px" width="491px" height="190px" viewbox="0 0 491 190" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink"><image externalResourcesRequired="true" xmlns="http://www.w3.org/2000/svg" x="0%" y="0%" height="100%" width="100%" xlink:href="https://www.google.com/logos/doodles/2013/erwin_schrdingers_126th_birthday-2002007-hp.jpg" xmlns:xlink="http://www.w3.org/1999/xlink"/></svg>

background-image: url('data:image/svg+xml;base64,PHN2ZyB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjQ5MXB4IiBoZWlnaHQ9IjE5MHB4IiB2aWV3Ym94PSIwIDAgNDkxIDE5MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48aW1hZ2UgZXh0ZXJuYWxSZXNvdXJjZXNSZXF1aXJlZD0idHJ1ZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4PSIwJSIgeT0iMCUiIGhlaWdodD0iMTAwJSIgd2lkdGg9IjEwMCUiIHhsaW5rOmhyZWY9Imh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vbG9nb3MvZG9vZGxlcy8yMDEzL2Vyd2luX3NjaHJkaW5nZXJzXzEyNnRoX2JpcnRoZGF5LTIwMDIwMDctaHAuanBnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIvPjwvc3ZnPg==');
Run Code Online (Sandbox Code Playgroud)