Обновить изображение с новым по тому же url

Я получаю доступ к ссылке на моем сайте, которая будет предоставлять новое изображение каждый раз, когда к нему обращаются.

проблема, с которой я сталкиваюсь, заключается в том, что если я попытаюсь загрузить изображение в фоновом режиме, а затем обновить его на странице, изображение не изменится, хотя оно обновляется при перезагрузке страницы.

var newImage = new Image();
newImage.src = "http://localhost/image.jpg";

function updateImage()
{
if(newImage.complete) {
    document.getElementById("theText").src = newImage.src;
    newImage = new Image();
    number++;
    newImage.src = "http://localhost/image/id/image.jpg?time=" + new Date();
}

    setTimeout(updateImage, 1000);
}

заголовки, как их видит FireFox:

HTTP/1.x 200 OK
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: image/jpeg
Expires: Fri, 30 Oct 1998 14:19:41 GMT
Server: Microsoft-HTTPAPI/1.0
Date: Thu, 02 Jul 2009 23:06:04 GMT

мне нужно принудительно обновить только это изображение на странице. Есть идеи?

16 ответов


попробуйте добавить cachebreaker в конце url:

newImage.src = "http://localhost/image.jpg?" + new Date().getTime();

это автоматически добавит текущую метку времени при создании изображения, и это заставит браузер снова искать изображение вместо того, чтобы получать его в кэше.


я видел много вариаций в ответах на то, как это сделать, поэтому я подумал, что суммирую их здесь (плюс добавить 4-й метод моего собственного изобретения):


(1) добавьте уникальный параметр запроса перебора кэша в URL-адрес, например:

newImage.src = "image.jpg?t=" + new Date().getTime();

плюсы: 100% надежное, быстрое & легкое для того чтобы понять и снабдить.

плюсы: обходит кэширование в целом, что означает ненужные задержки и использование полосы пропускания всякий раз, когда изображение не изменить между видами. Потенциально заполнит кэш браузера (и любые промежуточные кэши) многими, многими копиями точно такого же изображения! Также требуется изменить URL изображения.

когда использовать: используйте, когда изображение постоянно меняется, например, для веб-камеры в прямом эфире. Если вы используете этот метод, убедитесь, что обслуживать сами изображения с Cache-control: no-cache HTTP-заголовки!!! (часто Это можно настроить с помощью a .файл htaccess). Иначе вы будете постепенно заполнять кэши со старыми версиями изображения!


(2) добавьте параметр запроса в URL-адрес, который изменяется только тогда, когда файл делает, например:

echo '<img src="image.jpg?m=' . filemtime('image.jpg') . '">';

(это PHP-серверный код, но важным моментом здесь является только это ?m=[файл last-modified time] строка запроса добавляется к имени файла).

плюсы: 100% надежный, быстрый & легкий для того чтобы понять и снабдить, и сохраняет преимущества кэширования отлично.

плюсы: требуется изменить URL-адрес изображения. Кроме того, немного больше работы для сервера - он должен получить доступ к файлу-время последнего изменения. Кроме того, требуется информация на стороне сервера, поэтому не подходит для чисто клиентского решения только для проверки обновленного образа.

когда использовать: когда вы хотите кэшировать изображения, но, возможно, потребуется обновлять их на сервере время от времени без изменяющий именем. И когда вы можете легко убедиться, что правильная строка запроса добавлена к каждому экземпляру изображения в вашем HTML.


(3) служите ваши изображения с заголовком Cache-control: max-age=0, must-revalidate и добавить уникальный memcache для - перебор идентификатора фрагмента URL-адреса, например:

newImage.src = "image.jpg#" + new Date().getTime();

идея здесь в том, что заголовок Cache-control помещает изображения в кэш браузера, но сразу же помечает их устаревшими, так что и каждый раз, когда они повторно отображаются браузер должен проверить с сервером, чтобы увидеть, если они изменились. Это гарантирует, что браузер http Кеша всегда возвращает последнюю копию изображения. Однако браузеры часто повторно используют копию изображения в памяти, если она у них есть, и даже не проверяют свой http-кэш в этом случае. Для предотвращения этого используется идентификатор фрагмента: сравнение образа в памяти srcвключает идентификатор фрагмента, но он удаляется перед запросом кэша HTTP. (Так, например, image.jpg#A и image.jpg#B оба могут отображаться из image.jpg запись в кэше HTTP браузера, но image.jpg#B никогда не будет отображаться с использованием сохраненных в памяти данных изображения, когда image.jpg#A последний раз отображался).

плюсы: правильно использует механизмы кэширования HTTP и использует кэшированные изображения, если они не изменились. Работает для серверов, которые задыхаются от строки запроса, добавленной в статический URL-адрес изображения (поскольку серверы никогда не видят идентификаторы фрагментов - они для собственное использование браузеров).

плюсы: полагается на несколько сомнительное (или, по крайней мере, плохо документированное) поведение браузеров в отношении изображений с идентификаторами фрагментов в их URL-адресах (однако я успешно протестировал это в FF27, Chrome33 и IE11). По-прежнему отправляет запрос на повторную проверку на сервер для каждого представления изображения, что может быть излишним, если изображения меняются редко и / или задержка является большой проблемой (так как вам нужно ждать ответа на повторную проверку даже когда кэшированное изображение все еще хорошо). Требуется изменить URL-адреса изображений.

когда использовать: используйте, когда изображения могут часто меняться или должны периодически обновляться клиентом без участия сценария на стороне сервера, но где вы все еще хотите получить преимущество кэширования. Например, опрос живой веб-камеры, которая обновляет изображение нерегулярно каждые несколько минут. Кроме того, используйте вместо (1) или (2), Если ваш сервер не разрешает строки запросов на статическом изображении URL-адреса.


(4) принудительно обновите конкретное изображение с помощью Javascript, сначала загрузив его в скрытый <iframe> и затем вызов location.reload(true) на iframe contentWindow.

действия:

  • загрузите изображение для обновления в скрытый iframe. Это всего лишь шаг настройки - при желании это можно сделать задолго до фактического обновления. Это даже не имеет значения, если изображение не загружается при этом сцена!

  • как только это будет сделано, очистите все копии этого изображения на Вашей странице (- ах) или в любом месте в любых узлах DOM (даже за пределами страницы, хранящиеся в переменных javascript). Это необходимо, потому что в противном случае браузер может отображать изображение из устаревшей копии в памяти (IE11 особенно делает это): вам нужно убедиться, что все в памяти копии очищаются перед обновлением кэша HTTP. Если другой код javascript выполняется асинхронно, вам также может потребоваться чтобы предотвратить создание этим кодом новых копий обновляемого образа в то же время.

  • вызов iframe.contentWindow.location.reload(true). The true принудительно обход кэша, перезагрузка непосредственно с сервера и перезапись существующей кэшированной копии.

  • после окончания re-загрузка, восстановление заглушенных изображений. Теперь они должны отображать свежую версию с сервера!

для изображений одного домена, вы можно загрузить изображение в iframe напрямую. Для междоменных изображений вы должны вместо этого загрузить HTML-страницу из вашего домена который содержит изображение в <img> тег, в противном случае вы получите ошибку "отказано в доступе" при попытке вызвать iframe.contentWindow.reload(...).

плюсы: работает так же, как изображения.reload () функция you желаю дом был! Позволяет кэшировать изображения в обычном режиме (даже с датами истечения срока действия в будущем, если вы хотите их, тем самым избегая частые перепроверки). Позволяет обновить определенное изображение без изменения URL-адресов для этого изображения на текущей странице или на любых других страницах, используя только клиентский код.

плюсы: полагается на Javascript. Не 100% гарантирует правильную работу в каждом браузере (я успешно протестировал это в FF27, Chrome33 и IE11). Очень сложно по сравнению с другими методами.

когда использовать: когда у вас есть коллекция в основном статические изображения, которые вы хотели бы кэшировать, но вы все равно должны иметь возможность обновлять их время от времени и получать немедленную визуальную обратную связь о том, что обновление имело место. (Особенно, когда просто обновление всей страницы браузера не будет работать, как в некоторых веб-приложениях, построенных на AJAX, например). И когда методы (1) - (3) невозможны, потому что (по какой-либо причине) вы не можете изменить все URL-адреса, которые потенциально могут отображать изображение, которое вам нужно обновить. (Обратите внимание, что с помощью этих 3 способов изображение будет обновлено, но если другое страница затем пытается отобразить это изображение без соответствующий идентификатор querystring или фрагмента, вместо него может отображаться более старая версия).

подробности реализации этого в сказочной надежной и гибкой манере приведены ниже:

предположим, что ваш сайт содержит пустой пиксель 1x1 .gif по URL пути /img/1x1blank.gif, а также имеет следующий однострочный PHP скрипт (требуется только для применение принудительного обновления к кросс-домен изображения и могут быть переписаны на любом языке сценариев на стороне сервера, конечно) по URL-адресу/echoimg.php:

<img src="<?=htmlspecialchars(@$_GET['src'],ENT_COMPAT|ENT_HTML5,'UTF-8')?>">

затем, вот реалистичная реализация того, как вы могли бы сделать все это в Javascript. Это выглядит немного сложно, но есть много комментариев, и важной функцией является просто forceImgReload () - первые два просто пустых и незаполненных изображения и должны быть разработаны для эффективной работы с вашими собственными HTML, поэтому кодируйте их так, как лучше всего работает для вас; большая часть осложнений в них может быть ненужной для вашего сайта:

// This function should blank all images that have a matching src, by changing their src property to /img/1x1blank.gif.
// ##### You should code the actual contents of this function according to your page design, and what images there are on them!!! #####
// Optionally it may return an array (or other collection or data structure) of those images affected.
// This can be used by imgReloadRestore() to restore them later, if that's an efficient way of doing it (otherwise, you don't need to return anything).
// NOTE that the src argument here is just passed on from forceImgReload(), and MAY be a relative URI;
// However, be aware that if you're reading the src property of an <img> DOM object, you'll always get back a fully-qualified URI,
// even if the src attribute was a relative one in the original HTML.  So watch out if trying to compare the two!
// NOTE that if your page design makes it more efficient to obtain (say) an image id or list of ids (of identical images) *first*, and only then get the image src,
// you can pass this id or list data to forceImgReload() along with (or instead of) a src argument: just add an extra or replacement parameter for this information to
// this function, to imgReloadRestore(), to forceImgReload(), and to the anonymous function returned by forceImgReload() (and make it overwrite the earlier parameter variable from forceImgReload() if truthy), as appropriate.
function imgReloadBlank(src)
{
  // ##### Everything here is provisional on the way the pages are designed, and what images they contain; what follows is for example purposes only!
  // ##### For really simple pages containing just a single image that's always the one being refreshed, this function could be as simple as just the one line:
  // ##### document.getElementById("myImage").src = "/img/1x1blank.gif";

  var blankList = [],
      fullSrc = /* Fully qualified (absolute) src - i.e. prepend protocol, server/domain, and path if not present in src */,
      imgs, img, i;

  for each (/* window accessible from this one, i.e. this window, and child frames/iframes, the parent window, anything opened via window.open(), and anything recursively reachable from there */)
  {
    // get list of matching images:
    imgs = theWindow.document.body.getElementsByTagName("img");
    for (i = imgs.length; i--;) if ((img = imgs[i]).src===fullSrc)  // could instead use body.querySelectorAll(), to check both tag name and src attribute, which would probably be more efficient, where supported
    {
      img.src = "/img/1x1blank.gif";  // blank them
      blankList.push(img);            // optionally, save list of blanked images to make restoring easy later on
    }
  }

  for each (/* img DOM node held only by javascript, for example in any image-caching script */) if (img.src===fullSrc)
  {
    img.src = "/img/1x1blank.gif";   // do the same as for on-page images!
    blankList.push(img);
  }

  // ##### If necessary, do something here that tells all accessible windows not to create any *new* images with src===fullSrc, until further notice,
  // ##### (or perhaps to create them initially blank instead and add them to blankList).
  // ##### For example, you might have (say) a global object window.top.blankedSrces as a propery of your topmost window, initially set = {}.  Then you could do:
  // #####
  // #####     var bs = window.top.blankedSrces;
  // #####     if (bs.hasOwnProperty(src)) bs[src]++; else bs[src] = 1;
  // #####
  // ##### And before creating a new image using javascript, you'd first ensure that (blankedSrces.hasOwnProperty(src)) was false...
  // ##### Note that incrementing a counter here rather than just setting a flag allows for the possibility that multiple forced-reloads of the same image are underway at once, or are overlapping.

  return blankList;   // optional - only if using blankList for restoring back the blanked images!  This just gets passed in to imgReloadRestore(), it isn't used otherwise.
}




// This function restores all blanked images, that were blanked out by imgReloadBlank(src) for the matching src argument.
// ##### You should code the actual contents of this function according to your page design, and what images there are on them, as well as how/if images are dimensioned, etc!!! #####
function imgReloadRestore(src,blankList,imgDim,loadError);
{
  // ##### Everything here is provisional on the way the pages are designed, and what images they contain; what follows is for example purposes only!
  // ##### For really simple pages containing just a single image that's always the one being refreshed, this function could be as simple as just the one line:
  // ##### document.getElementById("myImage").src = src;

  // ##### if in imgReloadBlank() you did something to tell all accessible windows not to create any *new* images with src===fullSrc until further notice, retract that setting now!
  // ##### For example, if you used the global object window.top.blankedSrces as described there, then you could do:
  // #####
  // #####     var bs = window.top.blankedSrces;
  // #####     if (bs.hasOwnProperty(src)&&--bs[src]) return; else delete bs[src];  // return here means don't restore until ALL forced reloads complete.

  var i, img, width = imgDim&&imgDim[0], height = imgDim&&imgDim[1];
  if (width) width += "px";
  if (height) height += "px";

  if (loadError) {/* If you want, do something about an image that couldn't load, e.g: src = "/img/brokenImg.jpg"; or alert("Couldn't refresh image from server!"); */}

  // If you saved & returned blankList in imgReloadBlank(), you can just use this to restore:

  for (i = blankList.length; i--;)
  {
    (img = blankList[i]).src = src;
    if (width) img.style.width = width;
    if (height) img.style.height = height;
  }
}




// Force an image to be reloaded from the server, bypassing/refreshing the cache.
// due to limitations of the browser API, this actually requires TWO load attempts - an initial load into a hidden iframe, and then a call to iframe.contentWindow.location.reload(true);
// If image is from a different domain (i.e. cross-domain restrictions are in effect, you must set isCrossDomain = true, or the script will crash!
// imgDim is a 2-element array containing the image x and y dimensions, or it may be omitted or null; it can be used to set a new image size at the same time the image is updated, if applicable.
// if "twostage" is true, the first load will occur immediately, and the return value will be a function
// that takes a boolean parameter (true to proceed with the 2nd load (including the blank-and-reload procedure), false to cancel) and an optional updated imgDim.
// This allows you to do the first load early... for example during an upload (to the server) of the image you want to (then) refresh.
function forceImgReload(src, isCrossDomain, imgDim, twostage)
{
  var blankList, step = 0,                                // step: 0 - started initial load, 1 - wait before proceeding (twostage mode only), 2 - started forced reload, 3 - cancelled
      iframe = window.document.createElement("iframe"),   // Hidden iframe, in which to perform the load+reload.
      loadCallback = function(e)                          // Callback function, called after iframe load+reload completes (or fails).
      {                                                   // Will be called TWICE unless twostage-mode process is cancelled. (Once after load, once after reload).
        if (!step)  // initial load just completed.  Note that it doesn't actually matter if this load succeeded or not!
        {
          if (twostage) step = 1;  // wait for twostage-mode proceed or cancel; don't do anything else just yet
          else { step = 2; blankList = imgReloadBlank(src); iframe.contentWindow.location.reload(true); }  // initiate forced-reload
        }
        else if (step===2)   // forced re-load is done
        {
          imgReloadRestore(src,blankList,imgDim,(e||window.event).type==="error");    // last parameter checks whether loadCallback was called from the "load" or the "error" event.
          if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
        }
      }
  iframe.style.display = "none";
  window.parent.document.body.appendChild(iframe);    // NOTE: if this is done AFTER setting src, Firefox MAY fail to fire the load event!
  iframe.addEventListener("load",loadCallback,false);
  iframe.addEventListener("error",loadCallback,false);
  iframe.src = (isCrossDomain ? "/echoimg.php?src="+encodeURIComponent(src) : src);  // If src is cross-domain, script will crash unless we embed the image in a same-domain html page (using server-side script)!!!
  return (twostage
    ? function(proceed,dim)
      {
        if (!twostage) return;
        twostage = false;
        if (proceed)
        {
          imgDim = (dim||imgDim);  // overwrite imgDim passed in to forceImgReload() - just in case you know the correct img dimensions now, but didn't when forceImgReload() was called.
          if (step===1) { step = 2; blankList = imgReloadBlank(src); iframe.contentWindow.location.reload(true); }
        }
        else
        {
          step = 3;
          if (iframe.contentWindow.stop) iframe.contentWindow.stop();
          if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
        }
      }
    : null);
}

затем, чтобы принудительно обновить изображение находится на том же домене, что и ваша страница, вы можете просто сделать:

forceImgReload("myimage.jpg");

чтобы обновить изображение из другого места (кросс-домен):

forceImgReload("http://someother.server.com/someimage.jpg", true);

более продвинутым приложением может быть перезагрузка изображения после загрузки новой версии на ваш сервер, подготовка начального этапа перезагрузки процесс одновременно с загрузкой, чтобы минимизировать видимую задержку перезагрузки для пользователя. Если вы делаете загрузку через AJAX, и сервер возвращает очень простой массив JSON [успех, ширина, высота] , то ваш код может выглядеть примерно так:

// fileForm is a reference to the form that has a the <input typ="file"> on it, for uploading.
// serverURL is the url at which the uploaded image will be accessible from, once uploaded.
// The response from uploadImageToServer.php is a JSON array [success, width, height]. (A boolean and two ints).
function uploadAndRefreshCache(fileForm, serverURL)
{
  var xhr = new XMLHttpRequest(),
      proceedWithImageRefresh = forceImgReload(serverURL, false, null, true);
  xhr.addEventListener("load", function(){ var arr = JSON.parse(xhr.responseText); if (!(arr&&arr[0])) { proceedWithImageRefresh(false); doSomethingOnUploadFailure(...); } else { proceedWithImageRefresh(true,[arr[1],ar[2]]); doSomethingOnUploadSuccess(...); }});
  xhr.addEventListener("error", function(){ proceedWithImageRefresh(false); doSomethingOnUploadError(...); });
  xhr.addEventListener("abort", function(){ proceedWithImageRefresh(false); doSomethingOnUploadAborted(...); });
  // add additional event listener(s) to track upload progress for graphical progress bar, etc...
  xhr.open("post","uploadImageToServer.php");
  xhr.send(new FormData(fileForm));
}

последнее примечание: хотя этот раздел посвящен изображениям, он потенциально применим и к другим типам файлов или ресурсов. Например, предотвращение использования устаревших скриптов или css-файлов или, возможно, даже обновление обновленные PDF-документы (используя (4), только если настроен на открытие в браузере). В этих случаях метод (4) может потребовать некоторых изменений в приведенном выше javascript.


в качестве альтернативы...

newImage.src = "http://localhost/image.jpg?" + new Date().getTime();

...похоже, что...

newImage.src = "http://localhost/image.jpg#" + new Date().getTime();

...достаточно, чтобы обмануть кэш браузера, не обходя любые восходящие кэши, предполагая, что вы вернули правильный Cache-Control заголовки. Хотя можно использовать...

Cache-Control: no-cache, must-revalidate

...вы теряете преимущества If-Modified-Since или If-None-Match заголовки, что-то вроде...

Cache-Control: max-age=0, must-revalidate

...должен запретить браузеру повторно загружать все изображение, если оно на самом деле не измененный. Протестировано и работает на IE, Firefox и Chrome. Досадно, что это не удается на Safari, Если вы не используете...

Cache-Control: no-store

...хотя это все еще может быть предпочтительнее, чем заполнение восходящих кэшей сотнями одинаковых изображений, особенно когда они работают на вашем собственном сервере. ;-)

обновление (2014-09-28): в настоящее время это выглядит как Cache-Control: no-store необходим и для Chrome.


после создания нового изображения вы удаляете старое изображение из DOM и заменяете его новым?

вы можете захватывать новые изображения каждый вызов updateImage, но не добавлять их на страницу.

есть несколько способов сделать это. Что-то вроде этого сработает.

function updateImage()
{
    var image = document.getElementById("theText");
    if(image.complete) {
        var new_image = new Image();
        //set up the new image
        new_image.id = "theText";
        new_image.src = image.src;           
        // insert new image and remove old
        image.parentNode.insertBefore(new_image,image);
        image.parentNode.removeChild(image);
    }

    setTimeout(updateImage, 1000);
}

после того, как это работает, если все еще есть проблемы, это, вероятно, проблема кэширования, как говорят другие ответы.


один ответ на hackishly добавить GET-параметр запроса, как было предложено.

лучший ответ-выдать пару дополнительных опций в вашем HTTP-заголовке.

Pragma: no-cache
Expires: Fri, 30 Oct 1998 14:19:41 GMT
Cache-Control: no-cache, must-revalidate

предоставляя дату в прошлом, она не будет кэшироваться браузером. Cache-Control был добавлен в HTTP / 1.1, и тег must-revalidate указывает, что прокси никогда не должны обслуживать старое изображение даже при смягчающих обстоятельствах, а Pragma: no-cache на самом деле не нужно для текущего современного браузеры / кэши, но могут помочь с некоторыми грубыми сломанными старыми реализациями.


function reloadImage(imageId)
{
   path = '../showImage.php?cache='; //for example
   imageObject = document.getElementById(imageId);
   imageObject.src = path + (new Date()).getTime();
}
<img src='../showImage.php' id='myimage' />

<br/>

<input type='button' onclick="reloadImage('myimage')" />

то, что я в конечном итоге сделал, было сопоставление сервера с любым запросом на изображение в этом каталоге с источником, который я пытался обновить. Затем я попросил таймер добавить номер в конец имени, чтобы DOM увидел его как новое изображение и загрузил его.

Э. Г.

http://localhost/image.jpg
//and
http://localhost/image01.jpg

запросит тот же код генерации изображений, но он будет выглядеть как разные изображения в браузере.

var newImage = new Image();
newImage.src = "http://localhost/image.jpg";
var count = 0;
function updateImage()
{
    if(newImage.complete) {
        document.getElementById("theText").src = newImage.src;
        newImage = new Image();
        newImage.src = "http://localhost/image/id/image" + count++ + ".jpg";
    }
    setTimeout(updateImage, 1000);
}

попробуйте использовать бесполезную строку запроса, чтобы сделать ее уникальным url:

function updateImage()
{
    if(newImage.complete) {
        document.getElementById("theText").src = newImage.src;
        newImage = new Image();
        number++;
        newImage.src = "http://localhost/image.jpg?" + new Date();
    }

    setTimeout(updateImage, 1000);
}

document.getElementById("img-id").src = document.getElementById("img-id").src

установите свой собственный src в качестве src.


у меня было требование: 1) не могу добавить ?var=xx к изображению 2) он должен работать в междоменном

мне очень нравится вариант № 4 в ответ С одним но:

  • он имеет проблемы с надежной работой с crossdomain (и для этого требуется коснуться кода сервера).

мой быстрый и грязный способ:

  1. создать скрытый iframe
  2. загрузите в него текущую страницу (да вся страница)
  3. iframe.contentWindow.location.reload(true);
  4. переустановите Источник изображения на себя

здесь

function RefreshCachedImage() {
    if (window.self !== window.top) return; //prevent recursion
    var $img = $("#MYIMAGE");
    var src = $img.attr("src");
    var iframe = document.createElement("iframe");
    iframe.style.display = "none";
    window.parent.document.body.appendChild(iframe);
    iframe.src = window.location.href;
    setTimeout(function () {
        iframe.contentWindow.location.reload(true);
        setTimeout(function () {
            $img.removeAttr("src").attr("src", src);
        }, 2000);
    }, 2000);
}

Да, я знаю, setTimeout... Вы должны изменить это на правильное выполнение-мероприятий.


Я решил эту проблему путем отправки данных через сервлет.

response.setContentType("image/png");
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
response.setDateHeader("Expires", 0);

BufferedImage img = ImageIO.read(new File(imageFileName));

ImageIO.write(img, "png", response.getOutputStream());

затем со страницы вы просто даете ему сервлет с некоторыми параметрами, чтобы захватить правильный файл изображения.

<img src="YourServlet?imageFileName=imageNum1">

вот мое решение. Все очень просто. Планирование кадров может быть лучше.

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">      
        <title>Image Refresh</title>
    </head>

    <body>

    <!-- Get the initial image. -->
    <img id="frame" src="frame.jpg">

    <script>        
        // Use an off-screen image to load the next frame.
        var img = new Image();

        // When it is loaded...
        img.addEventListener("load", function() {

            // Set the on-screen image to the same source. This should be instant because
            // it is already loaded.
            document.getElementById("frame").src = img.src;

            // Schedule loading the next frame.
            setTimeout(function() {
                img.src = "frame.jpg?" + (new Date).getTime();
            }, 1000/15); // 15 FPS (more or less)
        })

        // Start the loading process.
        img.src = "frame.jpg?" + (new Date).getTime();
    </script>
    </body>
</html>

сильно основанный на коде #4 Doin, приведенный ниже пример упрощает этот код, используя document.write вместо src на iframe для поддержки CORS. Также фокусируется только на переборе кэша браузера, а не на перезагрузке каждого изображения на странице.

ниже написано typescript и использует angular $q библиотека обещаний, просто fyi, но должно быть достаточно легко портировать на ванильный javascript. Метод предназначен для жизни внутри класса typescript.

возвращает обещание, которое будет разрешено, когда iframe завершит перезагрузку. Не сильно проверено, но работает хорошо для нас.

    mmForceImgReload(src: string): ng.IPromise<void> {
        var deferred = $q.defer<void>();
        var iframe = window.document.createElement("iframe");

        var firstLoad = true;
        var loadCallback = (e) => {
            if (firstLoad) {
                firstLoad = false;
                iframe.contentWindow.location.reload(true);
            } else {
                if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
                deferred.resolve();
            }
        }
        iframe.style.display = "none";
        window.parent.document.body.appendChild(iframe);
        iframe.addEventListener("load", loadCallback, false);
        iframe.addEventListener("error", loadCallback, false);
        var doc = iframe.contentWindow.document;
        doc.open();
        doc.write('<html><head><title></title></head><body><img src="' + src + '"></body></html>');
        doc.close();
        return deferred.promise;
    }

я использовал приведенную ниже концепцию первой привязки изображения с ложным (буферным) url-адресом и следующей привязки его с допустимым url-адресом.

imgcover.ImageUrl = ConfigurationManager.AppSettings["profileLargeImgPath"] + "Myapp_CoverPic_" + userid + "Buffer.jpg";

imgcover.ImageUrl = ConfigurationManager.AppSettings["profileLargeImgPath"] + "Myapp_CoverPic_" + userid + ".jpg";

таким образом, я заставляю браузер обновляться с допустимым url-адресом.


<img src='someurl.com/someimage.ext' onload='imageRefresh(this, 1000);'>

затем ниже в некотором javascript

<script language='javascript'>
 function imageRefresh(img, timeout) {
    setTimeout(function() {
     var d = new Date;
     var http = img.src;
     if (http.indexOf("&d=") != -1) { http = http.split("&d=")[0]; } 

     img.src = http + '&d=' + d.getTime();
    }, timeout);
  }
</script>

и так, что это делает, когда изображение загружается, планирует его на перезарядку в 1 секунду. Я использую это на странице с камер видеонаблюдения различного типа.


следующий код полезен для обновления изображения при нажатии кнопки.

function reloadImage(imageId) {
   imgName = 'vishnu.jpg'; //for example
   imageObject = document.getElementById(imageId);
   imageObject.src = imgName;
}

<img src='vishnu.jpg' id='myimage' />

<input type='button' onclick="reloadImage('myimage')" />