2013-08-01 42 views
6

Tôi đang phục vụ một hình ảnh giữ chỗ với một HTTP header Refresh, như thế này:img thẻ HTML không tôn vinh header HTTP Refresh (nhưng tải URL hình ảnh trong trình duyệt không)

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 

Nếu tôi tải hình ảnh URL trình giữ chỗ trong cửa sổ đầy đủ, nội dung được làm mới sau 10 giây, nhưng nếu tôi đặt cùng một URL trong thẻ hình ảnh src thuộc tính, hình ảnh sẽ không bao giờ được làm mới (được thử nghiệm trong Chrome và FF).

Tại sao tôi làm điều này? Tôi có một ứng dụng mà hình thu nhỏ của một tài liệu mất một vài giây để được tạo ra bởi máy chủ (nó là một kết xuất SVG phức tạp). Khi người dùng truy cập danh sách tài liệu ngay sau khi tạo tài liệu mới, hình thu nhỏ có thể chưa có. Tôi đã cố gắng sử dụng hình ảnh trình giữ chỗ có tiêu đề làm mới để tải hình thu nhỏ thực sau vài giây.

Tôi không thể nhớ lại, nhưng trở lại những ngày cũ của trình duyệt Netscape, một cái gì đó giống như tiêu đề làm mới là cách chúng tôi tấn công hoạt hình đôi khi (trước cả Flash - tôi là thời tiền sử hay gì?). Chúng tôi gọi nó là "đẩy máy chủ" (tôi đoán là từ thông dụng được tái chế với Comet model).

Tôi đang sử dụng Angular.js ở phía máy khách (phía máy chủ là Django + uWSGI + Nginx), vì vậy nó phải đủ dễ dàng để hack cái gì đó bằng javascript, nhưng tôi tò mò: là có bất kỳ mẹo nào (mà không có javascript) để làm cho thẻ hình ảnh tải một nguồn khác sau một vài giây?

(Tôi sẽ tag Django này và Nginx cũng vì có thể ai đó biết một giải pháp server-side)

Trả lời

1

Giải thích

Khi bạn mở một hình ảnh trực tiếp trong trình duyệt, nó quấn lên như một tài liệu HTML.

Chuyển đến jpg doodle mới nhất của google sau đó mở bảng điều khiển HTML của bạn (http://www.google.com/logos/doodles/2013/erwin_schrdingers_126th_birthday-2002007-hp.jpg).

Trong Chrome, bạn sẽ nhận được:

<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> 

này "gói" không được thực hiện cho của IMG tag src được bên trong của một tài liệu.

Giải pháp

Nếu bạn có ý định chỉ sử dụng HTTP header bạn đang mắc kẹt với multipart/x-hỗn hợp thay thế cho mô tả bởi @JamesHolderness, nhưng lưu ý rời khỏi các kết nối HTTP treo mở như thế này có thể làm tổn thương hiệu suất máy chủ của bạn và có khả năng mở bạn tới một cuộc tấn công DDoS.

Tôi sẽ đề xuất sử dụng hoạt ảnh CSS/chuyển đổi để tải hình ảnh một cách lười biếng. Rất tiếc, chỉ Chrome hỗ trợ hoạt ảnh nền (hình ảnh thuộc tính CSS). Một tùy chọn khác sẽ được hiển thị: không có gì vì hình ảnh không tải cho đến khi phần tử được hiển thị, nhưng không có trình duyệt nào hỗ trợ hoạt ảnh hoặc chuyển đổi trên màn hình (thuộc tính CSS).

Đây là Chrome chỉ, CSS chỉ giải pháp http://jsfiddle.net/r2Tag/

HTML

<div id="thumbnail"></div> 

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'); 
} } 

EDIT Nếu bạn sử dụng một dữ liệu URI SVG là background-image bạn động để bạn có thể phá vỡ trình phân tích cú pháp của Chrome trước khi tải hình ảnh.

Ví dụ 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=='); 
+0

Tôi ước gì tôi có thể chia tiền thưởng; giải pháp solomonic câm của tôi là chấp nhận câu trả lời của bạn và trao tiền thưởng cho James (tôi có lẽ sẽ khiến cả hai bạn khó chịu, nhưng tốt, cuộc sống là không công bằng). –

+0

@PauloScardine - Cả hai câu trả lời đều thiếu một giải pháp an toàn & phổ quát. Khi bạn bắt đầu nghịch với các tiêu đề HTTP và các kết nối treo hoặc CSS cụ thể của trình duyệt, không phải là tối ưu. Các giải pháp an toàn và phổ biến duy nhất là JavaScript hoặc IFRAME với tính năng làm mới META. –

+0

Tôi không gặp vấn đề gì khi không chấp nhận câu trả lời của mình, nhưng tôi ngạc nhiên về giải pháp CSS đã làm việc cho bạn (trên bất kỳ trình duyệt nào). Đó là một trong những điều đầu tiên tôi đã thử, nhưng đối với tôi, nó dường như luôn tải cả hai hình ảnh lên phía trước, mặc dù hình ảnh thứ hai chỉ được hiển thị sau đó. Tôi nghĩ ý tưởng là để tải hình ảnh thứ hai sau một sự chậm trễ (một khi bạn biết nó sẽ sẵn sàng), không chỉ hiển thị nó sau một sự chậm trễ. –

0

Bạn có thể cố gắng để đưa hình ảnh của bạn vào khung nội tuyến, và trả về một trang cho rằng iframe với Refresh tiêu đề.

Nhưng, nghiêm túc, hãy sử dụng JS.

+0

Tôi đã thực hiện một "refresh" chỉ thị trong góc mà không được công việc, nhưng tôi vẫn tò mò nếu có sự kết hợp của tiêu đề có thể làm các trick. –

3

Nếu bạn không cần hỗ trợ IE, và thế hệ svg của bạn không mất quá nhiều thời gian, bạn có thể đạt được hiệu ứng tương tự bằng cách sử dụng Kiểu nội dung multipart/x-mixed-replace. Một cái gì đó như thế này:

Content-Type: multipart/x-mixed-replace; boundary=myboundary 

Đối với nội dung thực tế của bạn, bạn bắt đầu bằng cách viết ra những hình ảnh giữ chỗ như thế này:

--myboundary 
Content-Type: image/jpeg 
Content-Length: <size of the image in bytes> 

<binary image data + CR/LF> 

Sau đó, ngay lập tức tuôn đầu ra, nhưng giữ kết nối sống (ví dụ này sẽ sử dụng một Mã hóa Chuyển mã chunked).

Bây giờ bạn có thể bắt đầu tạo svg của bạn, và khi nó được hoàn tất, hãy viết nó ra như thế này:

--myboundary 
Content-Type: image/svg+xml 
Content-Length: <size of the image in bytes> 

<svg image data + CR/LF> 
--myboundary-- 

này về cơ bản là như thế nào streaming M-JPEG công trình, chỉ trong trường hợp này các khung không phải là tất cả hình ảnh jpeg .