2013-10-22 30 views
2

所以我的頁面上有一個<img>標籤。如何複製img標籤與src不應該被緩存沒有HTTP請求?

<img id="the_image" src="/imageServlet"> 

讓我們假設/ imageServlet與一些HTTP響應頭指示瀏覽器不應該緩存這個圖像響應。在這種情況下,原因是該圖像可能包含敏感的員工信息,並且在某些國家/地區有法律規定,瀏覽器在沒有用戶同意的情況下不應將圖像保存在客戶機的硬盤驅動器上,以防機器被盜。我相信響應標題是Cache-Control: no-cache

我真的想要做的就是複製這個圖像標記,但我不希望爲此圖像發出另一個HTTP請求。

我的應用程序是一個單一的頁面,使用javascript我動態地這些圖片標籤 - 但現在我想在多個地方顯示相同的圖像。例如,該圖像可以是用戶的個人資料圖片的縮略圖版本。在一個地方,我將縮略圖顯示爲一個小列表,然後在單擊該用戶時在彈出窗口中顯示相同的圖像。

每次我用這個src創建一個新的<img>標記時,瀏覽器會重新調用服務器來檢索圖像。我不在乎用戶是否在瀏覽器上按下「刷新」,並且該圖像的新HTTP請求應該加載 - 但是在單個頁面加載時,圖像數據不應在內存中可用,因此無法重用這個?

我該如何解決這個問題?這極大地影響了頁面的性能,圖像在多個地方被重複使用和顯示,並且每次都需要重新加載(即使用戶沒有導航到任何其他頁面或刷新瀏覽器)。

這裏有一些代碼,我剛纔寫了一個想法,任何時候應用程序想要加載一個圖像,它會調用「loadImage」,它最終會用一些可以自由使用的HTML元素調用回調函數。這個想法應該是這個核心功能會創建圖像,但它會確保對於任何獨特的src只會有一個HTTP請求 - 無論HTTP響應標頭是否包含Cache-Control: no-cache

(function(){ 
    var HANDLERS = {}; 

    /** 
    * I want to keep around a cached "Image" then the "callback" will be called with a 
    * duplicate somehow - whatever comes back from here can be inserted somewhere, but 
    * hopefully no additional HTTP requests needs to be made!! 
    * @param {Image} img 
    * @return {Image} A copy of the incoming img 
    */ 
    function duplicateImage(img) { 
    // Does not work!! D'oh, is this even possible to achieve?? 
    return img.cloneNode(true); 
    } 

    /** 
    * Users can call this to load the image. The callback is called when the image is ready. 
    * In case the image fails the callback will be given an object that contains a success flag. 
    * 
    * Example: 
    * loadImage('/imageServlet?xxxx', function(result) { 
    * if (result.success) { $(body).append(result.image); } 
    * else { console.log("The image failed to load!") } 
    * }); 
    * 
    * @param {string} src The src for the image 
    * @param {function({success:boolean, image:Image})} callback Give a callback to be called when ready 
    */ 
    window.loadImage = function(src, callback) { 
    if (!HANDLERS[src]) { 
     var queue = []; 

     // This loadImage can be called more than once with the same src 
     // before the image has successfully loaded. We will queue up any 
     // callbacks and call them later, then replace this with function 
     // that will directly invoke the callback later. 
     HANDLERS[src] = function(callback) { 
     queue.push(callback); 
     } 

     // Create the image here, but do it only once!! 
     var el = new Image(); 

     // When the image loads, we will keep it around in the el 
     // variable, but the callback will be called with a copy 
     el.onload = function() { 
     el.onload = el.onerror = null; 
     var call = HANDLERS[src] = function(callback) { 
      callback({ 
      success: true, 
      image: duplicateImage(el) // This is where the image is duplicated! 
      }); 
     } 
     for (var i=0; i<queue.length; i++) { 
      call(queue[i]); 
     } 
     } 

     // This is just in case the image fails to load. Call any 
     // queued callbacks with the success false. 
     el.onerror = function() { 
     el.onload = el.onerror = null; 
     var call = HANDLERS[src] = function(callback) { 
      callback({success: false}); 
     } 
     for (var i=0; i<queue.length; i++) { 
      call(queue[i]); 
     } 
     } 
     el.src = src; 
    } 
    HANDLERS[src](callback); 
    } 
})(); 

回答

4

嘗試Ajax調用,當頁面已經開始得到的圖像數據,並分配到你想「複製」這些數據對圖像的「SRC」。

$.ajax({ 
    type: "GET", 
    url: 'some url', 
    datatype:"image/jpg", 
     success: function (data) { 
      $('#img1').attr('src', url.createObjectURL(data)); 
      $('#img2').attr('src', url.createObjectURL(data)); 
     } 
}); 

因爲這個寫入acutal圖像進入「SRC」費爾德,而不是一個鏈接,你可以在以後的時間複製從一個控件到另一個這一形象沒有更多的對服務器的請求非常簡單:

$('#img3').attr('src', $('#img2').attr('src')); 

非jQuery的版本

function myAjax() { 
    var xmlHttp = new XMLHttpRequest(); 
    var url="some url"; 
    xmlHttp.open("GET", url, true); 
    xmlHttp.setRequestHeader("Content-type", "image/jpg"); 
    xmlHttp.setRequestHeader("Connection", "close"); 
    xmlHttp.onreadystatechange = function() { 
     if(xmlHttp.readyState == 4 && xmlHttp.status == 200) { 
      document.getElementById('img1').setAttribute('src', xmlHttp.responseBinary); 
     } 
    } 
    xmlHttp.send(); 
} 
+0

我打算試試這個;不過,假設它確實有效,它只會在圖像的src使用與我當前使用的頁面相同的域時起作用。不過,就我而言,它將是同一個域,但它不會是任何src的通用解決方案。 – codefactor

+0

我認爲你的代碼中缺少一些東西。我嘗試設置像'$('#img1')。attr('src',data)'這樣的'src'屬性,但它不起作用。 – codefactor

+0

嗯,這是一個恥辱。你有試過另一個嗎? '的document.getElementById( 'IMG1')。setAttribute'?另外,確保jQuery實際上正確地選擇你的圖像 - 如果它沒有任何東西,它將會靜靜地失敗。 – binderbound

0

您可能希望在陣列存儲的文件名(「SRC」),使JavaScript可以判斷,如果圖像加載。您可以使用畫布來渲染圖像...一旦圖像加載到畫布中,就可以使用toDataURL()複製此圖像...無需從服務器中獲取圖像。

+0

畫布可能適用於FF/Chrome/Safari - 但不適用於IE。超過90%的用戶使用IE。 – codefactor

+0

哦,對不起...使用php..you可以將圖像轉換爲base64 ...並將其存儲在客戶端瀏覽器的數組中。要呈現圖片,您只需使用即可。 Hellgorithm

+0

你知道如何在JavaScript中創建「somebase64string」嗎?假設我有一些來自ajax調用的響應數據?我試過這個:http://stackoverflow.com/questions/13908019/display-image-in-src-tag-with-response-text-not-base64 - 但它沒有工作 – codefactor