私は私のサイト上のリンクにアクセスしています。リンクはアクセスされるたびに新しい画像を提供します。
私が遭遇している問題は、私がバックグラウンドで画像をロードしてそれからページ上のものを更新しようとしても、画像は変わらないということです - それは私がページをリロードするとき更新されますが。
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
ページ上のその画像だけを強制的に更新する必要があります。何か案は?
私がやってしまったのは、サーバーがそのディレクトリのイメージに対するリクエストを更新しようとしているソースにマッピングすることでした。それから、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の最後にキャッシュブレーカーを追加してみてください。
newImage.src = "http://localhost/image.jpg?" + new Date().getTime();
これにより、イメージを作成しているときに現在のタイムスタンプが自動的に追加され、ブラウザはキャッシュ内のイメージを取得するのではなく、イメージを再度検索するようになります。
私はこれを行う方法の答えに多くのバリエーションを見てきましたので、ここでそれらを要約すると思いました(さらに、自分の発明の4番目の方法を追加します):
newImage.src = "image.jpg?t=" + new Date().getTime();
長所: 100%信頼性が高く、素早く簡単に理解して実装できます。
短所:キャッシュを完全にバイパスします。つまり、ビュー間でイメージが変更されない場合は、不要な遅延と帯域幅の使用を意味します。ブラウザーのキャッシュ(および中間キャッシュ)を、まったく同じイメージの多数のコピーで潜在的に埋めます!また、画像のURLを変更する必要があります。
使用する場合:ライブWebカメラフィードなど、画像が常に変化している場合に使用します。このメソッドを使用する場合は、必ずCache-control: no-cache
HTTPヘッダーで画像自体を提供してください!!!(多くの場合、これは.htaccessファイル)。そうしないと、古いバージョンの画像でキャッシュが徐々にいっぱいになります!
echo '<img src="image.jpg?m=' . filemtime('image.jpg') . '">';
(これはPHPサーバー側コードですが、ここで重要な点は、?m =[file last-modified time]クエリ文字列がファイル名に追加されます)。
長所: 100%の信頼性、迅速かつ簡単に理解および実装、andはキャッシュの利点を完全に保持します。
短所:画像URLの変更が必要です。また、サーバーに対してもう少し作業が必要です。ファイルの最終変更時刻にアクセスする必要があります。また、サーバー側の情報が必要なので、更新されたイメージをチェックするための純粋にクライアント側のみのソリューションには適していません。
使用する場合:イメージをキャッシュしたいが、ファイル名自体を変更せずにサーバー側で時々更新する必要がある場合。そして、正しいクエリ文字列がHTMLのすべての画像インスタンスに追加されることを簡単に確認できる場合。
Cache-control: max-age=0, must-revalidate
で画像を提供し、次のような一意のmemcache-busting fragment identifierをURLに追加します。newImage.src = "image.jpg#" + new Date().getTime();
ここでの考え方は、キャッシュ制御ヘッダーが画像をブラウザのキャッシュに入れますが、すぐに古いものとしてマークするため、再表示されるたびに、ブラウザはサーバーで変更を確認する必要があります。これにより、ブラウザのHTTPキャッシュは常に画像の最新のコピーを返します。ただし、ブラウザは多くの場合、画像のメモリ内コピーを再利用し、その場合はHTTPキャッシュもチェックしません。これを防ぐために、フラグメント識別子が使用されます。メモリ内イメージsrc
'sの比較にはフラグメント識別子が含まれますが、HTTPキャッシュをクエリする前に削除されます。 (たとえば、image.jpg#A
とimage.jpg#B
は両方ともブラウザのHTTPキャッシュのimage.jpg
エントリから表示される場合がありますが、image.jpg#B
はメモリ内の保持画像を使用して表示されることはありませんimage.jpg#A
が最後に表示されたときのデータ)。
長所: HTTPキャッシュメカニズムを適切に使用し、変更されていない場合はキャッシュされたイメージを使用します。静的なイメージURLに追加されたクエリ文字列を絞るサーバーで機能します(サーバーはフラグメント識別子を決して参照しないため、ブラウザー自身が使用するためです)。
短所: URLにフラグメント識別子を含む画像に関して、ブラウザのやや疑わしい(または少なくとも不十分に文書化された)動作に依存しています(ただし、FF27、Chrome33、およびIE11でこれをテストしました)。すべての画像ビューに対してサーバーに再検証リクエストを送信しますが、画像がめったに変更されない場合や遅延が大きな問題である場合はやり過ぎになる可能性があります(キャッシュされた画像がまだ良好な場合でも再検証応答を待つ必要があるため) 。画像のURLを変更する必要があります。
使用する場合:画像が頻繁に変更される場合、またはサーバー側のスクリプトを使用せずにクライアントが断続的に更新する必要がある場合に使用しますが、キャッシュの利点が必要な場合に使用します。たとえば、数分ごとに不規則に画像を更新するライブWebカメラをポーリングします。または、サーバーが静的画像URLでクエリ文字列を許可しない場合は、(1)または(2)の代わりに使用します。
<iframe>
にロードし、次にiframeのcontentWindow
でlocation.reload(true)
を呼び出すことにより、Javascriptを使用して特定の画像を強制的に更新します。手順は次のとおりです。
更新する画像を非表示のiframeにロードします。これは単なるセットアップ手順です。必要に応じて、実際の更新のかなり前に実行できます。この段階で画像の読み込みに失敗しても問題ありません!
それが完了したら、ページまたはDOMノードの任意の場所(JavaScript変数に格納されているページ外のものも含む)で、そのイメージのすべてのコピーを空白にします。これは、ブラウザが古いメモリ内コピーから画像を表示する可能性があるために必要です(IE11は特にこれを行います):すべてを保証する必要がありますin-memoryHTTPキャッシュを更新する前に、コピーがクリアされます。他のJavaScriptコードが非同期で実行されている場合は、そのコードがその間にリフレッシュされるイメージの新しいコピーを作成しないようにする必要がある場合もあります。
iframe.contentWindow.location.reload(true)
を呼び出します。 true
は、キャッシュバイパスを強制し、サーバーから直接リロードし、既存のキャッシュコピーを上書きします。
終了したらre-loading、空白のイメージを復元します。サーバーから最新バージョンが表示されるはずです!
同じドメインの画像の場合、画像をiframeに直接読み込むことができます。クロスドメイン画像の場合、代わりに<img>
タグに画像を含むHTMLページをドメインからロードする必要があります。 iframe.contentWindow.reload(...)
を呼び出そうとすると、「アクセス拒否」エラーが発生します。
長所: image.reload()関数と同じように機能しますwishDOMにありました!画像を通常どおりにキャッシュできます(将来の有効期限が必要な場合でも、頻繁な再検証を回避できます)。クライアント側のコードのみを使用して、現在のページまたは他のページの画像のURLを変更せずに特定の画像を更新できます。
短所: Javascriptに依存しています。すべてのブラウザで正常に動作することが100%保証されるわけではありません(FF27、Chrome33、およびIE11でこれをテストしました)。他の方法に比べて非常に複雑です。
使用する場合:キャッシュしたい基本的に静的な画像のコレクションがあるが、時々それらを時々更新し、更新が行われたという視覚的なフィードバックを即座に得る必要がある場合。 (特に、たとえばAJAXに基づいて構築された一部のWebアプリのように、ブラウザページ全体を更新するだけでは機能しません)。また、(何らかの理由で)更新する必要がある画像を表示する可能性のあるすべてのURLを変更できないため、方法(1)〜(3)が実行可能でない場合。 (これらの3つの方法を使用すると画像が更新されますが、anotherページがその画像を表示しようとする場合 without適切なクエリ文字列またはフラグメント識別子、代わりに古いバージョンが表示される場合があります)。
妖精の堅牢で柔軟な方法でこれを実装する詳細を以下に示します。
WebサイトのURLパス/img/1x1blank.gif
に空白の1x1ピクセルの.gifが含まれており、次の1行のPHPスクリプト(強制更新をcross-domain画像。もちろん、サーバー側のスクリプト言語で書き換え可能です)URLパス/echoimg.php
:
<img src="<?=htmlspecialchars(@$_GET['src'],ENT_COMPAT|ENT_HTML5,'UTF-8')?>">
次に、これをすべてJavaScriptで行う方法の現実的な実装を示します。少し複雑に見えますが、多くのコメントがあり、重要な関数は単にforceImgReload()です。最初の2つの画像は空白で空白がないため、独自の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);
}
それがうまくいった後で、まだ問題があるならば、それはおそらく他の答えが話しているようなキャッシュの問題です。
1つの答えは、提案されているような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')" />
document.getElementById("img-id").src = document.getElementById("img-id").src
独自のsrcをそのsrcとして設定します。
それをユニークな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);
}
1)画像に?var=xx
を追加することはできません2)クロスドメインで動作するはずです
この答え の中の#4オプションがとても好きです
私の早くて汚い方法は:
iframe.contentWindow.location.reload(true);
ここにあります
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 ...あなたはそれを適切なonload-eventsに変更する必要があります。
次のコードは、ボタンがクリックされたときに画像を更新するのに役立ちます。
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')" />
私はサーブレットを通してデータを送り返すことによってこの問題を解決しました。
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">
<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秒で再ロードされるようにスケジュールすることです。私はさまざまな種類の家庭用防犯カメラのあるページでこれを使っています。
以下の例は、Doinの#4コードに大きく基づいており、CORSをサポートするためにsrc
内のiframe
の代わりにdocument.write
を利用してそのコードをかなり単純化しています。また、ページ上のすべての画像を再ロードするのではなく、ブラウザのキャッシュを無効にすることにのみ焦点を当てています。
以下はTypeScript
で書かれていて、angular
$ q promiseライブラリを使っています。メソッドは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;
}
これが私の解決策です。とても簡単です。フレームスケジューリングはもっと良いかもしれません。
<!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>