รีเฟรชภาพด้วยรูปภาพใหม่ใน URL เดียวกัน


333

ฉันกำลังเข้าถึงลิงก์ในเว็บไซต์ของฉันที่จะให้ภาพใหม่ทุกครั้งที่มีการเข้าถึง

ปัญหาที่ฉันพบคือถ้าฉันพยายามโหลดรูปภาพในพื้นหลังแล้วอัปเดตรูปภาพในหน้ารูปภาพจะไม่เปลี่ยน - แม้ว่าจะอัปเดตเมื่อฉันโหลดหน้าเว็บอีกครั้ง

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

ฉันต้องการบังคับให้รีเฟรชรูปภาพในหน้านั้น ความคิดใด ๆ


คำตอบ:


350

ลองเพิ่ม cachebreaker ที่ส่วนท้ายของ URL:

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

การดำเนินการนี้จะผนวกการประทับเวลาปัจจุบันโดยอัตโนมัติเมื่อคุณสร้างภาพและจะทำให้เบราว์เซอร์ค้นหารูปภาพอีกครั้งแทนที่จะดึงข้อมูลในแคช


26
ไม่ใช่วิธีแก้ปัญหาที่ดีมากเพราะจะทำให้แคช (ทั้งในพื้นที่และในต้นน้ำ) คำตอบของ Ayaมีวิธีที่ดีกว่าในการจัดการกับสิ่งนี้
Tgr

1
นอกจากนี้การแสดงรูปภาพเดียวกันที่อื่นโดยไม่มี "ตัวแบ่งแคช" ในภายหลังยังคงแสดงรุ่นแคชเก่า (อย่างน้อยก็ใน Firefox) ทั้งสองอย่าง และ # :(
T4NK3R

3
คุณสามารถทำรหัสได้น้อยลงด้วยสิ่งนี้:'image.jpg?' + (+new Date())
Lev Lukomsky

4
มีDate.now()ไว้สำหรับสิ่งนี้
vp_arth

2
ทำไมไม่Math.random()
Gowtham Gopalakrishnan

227

ฉันเห็นการเปลี่ยนแปลงมากมายในคำตอบสำหรับวิธีการทำเช่นนี้ดังนั้นฉันคิดว่าฉันจะสรุปได้ที่นี่ (บวกเพิ่มวิธีที่ 4 ของการประดิษฐ์ของฉันเอง):


(1) เพิ่มพารามิเตอร์คิวรีป้องกันการแคชที่ไม่ซ้ำกันไปยัง URL เช่น:

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

จุดเด่น:เชื่อถือได้ 100% รวดเร็วและง่ายต่อการเข้าใจและนำไปใช้

ข้อด้อย:บายพาสการแคชทั้งหมดหมายถึงความล่าช้าที่ไม่จำเป็นและการใช้แบนด์วิดท์เมื่อใดก็ตามที่ภาพไม่เปลี่ยนแปลงระหว่างมุมมอง อาจจะเติมแคชเบราว์เซอร์ (และแคชกลาง) ด้วยภาพจำนวนมากที่เหมือนกันหลายชุด! นอกจากนี้ต้องมีการแก้ไข URL ภาพ

เวลาที่จะใช้:ใช้เมื่อภาพมีการเปลี่ยนแปลงตลอดเวลาเช่นสำหรับฟีดเว็บแคมสด หากคุณใช้วิธีนี้ตรวจสอบให้แน่ใจว่าได้แสดงภาพตัวเองด้วยCache-control: no-cacheส่วนหัว HTTP !!! (บ่อยครั้งที่สิ่งนี้สามารถตั้งค่าได้โดยใช้ไฟล์. htaccess) ไม่เช่นนั้นคุณจะเติมแคชของรูปภาพในเวอร์ชันเก่าอย่างต่อเนื่อง!


(2) เพิ่มพารามิเตอร์การสืบค้นไปยัง URL ที่เปลี่ยนแปลงเฉพาะเมื่อไฟล์ทำเช่น:

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

(นั่นคือโค้ดฝั่งเซิร์ฟเวอร์ PHP แต่จุดสำคัญตรงนี้คือ? m = [เวลาแก้ไขล่าสุดของไฟล์] การสืบค้นจะถูกต่อท้ายชื่อไฟล์)

จุดเด่น:เชื่อถือได้ 100% รวดเร็วและง่ายต่อการเข้าใจและนำไปใช้และรักษาข้อได้เปรียบในการแคชอย่างสมบูรณ์แบบ

ข้อด้อย:ต้องแก้ไข URL รูปภาพ ยิ่งไปกว่านั้นการทำงานกับเซิร์ฟเวอร์จะต้องได้รับการเข้าถึงเวลาที่แก้ไขไฟล์ครั้งสุดท้าย นอกจากนี้ต้องใช้ข้อมูลฝั่งเซิร์ฟเวอร์ดังนั้นจึงไม่เหมาะสำหรับโซลูชันฝั่งไคลเอ็นต์เท่านั้นเพื่อตรวจสอบอิมเมจที่รีเฟรช

เวลาใช้:เมื่อคุณต้องการแคชรูปภาพ แต่อาจต้องอัปเดตที่เซิร์ฟเวอร์สิ้นสุดเป็นครั้งคราวโดยไม่ต้องเปลี่ยนชื่อไฟล์เอง และเมื่อคุณสามารถมั่นใจได้ว่ามีการเพิ่มการสืบค้นที่ถูกต้องในทุก ๆ ภาพใน HTML ของคุณ


(3) แสดงรูปภาพของคุณด้วยส่วนหัวCache-control: max-age=0, must-revalidateและเพิ่มmemcache ที่ไม่ซ้ำกัน - การระบุตัวแยกส่วนให้กับ URL เช่น:

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

แนวคิดในที่นี้คือส่วนหัวของการควบคุมแคชทำให้ภาพในแคชของเบราว์เซอร์ แต่จะทำเครื่องหมายว่าค้างทันทีดังนั้นทุกครั้งที่มีการแสดงเบราว์เซอร์ใหม่จะต้องตรวจสอบกับเซิร์ฟเวอร์เพื่อดูว่ามีการเปลี่ยนแปลงหรือไม่ วิธีนี้ช่วยให้มั่นใจได้ว่าแคช 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)บน contentWindowiframe

ขั้นตอนคือ:

  • โหลดภาพที่จะรีเฟรชเป็น iframe ที่ซ่อนอยู่ นี่เป็นเพียงขั้นตอนการตั้งค่า - สามารถทำได้ล่วงหน้าก่อนการรีเฟรชจริงหากต้องการ ไม่สำคัญว่ารูปภาพจะโหลดไม่ได้ในขั้นตอนนี้หรือไม่!

  • เมื่อทำเสร็จแล้วให้ล้างสำเนาของภาพนั้นในหน้าของคุณหรือที่ใดก็ได้ในโหนด DOM ใด ๆ (แม้จะอยู่นอกหน้าเว็บที่จัดเก็บในตัวแปรจาวาสคริปต์) สิ่งนี้จำเป็นเนื่องจากเบราว์เซอร์อาจแสดงรูปภาพจากสำเนาในหน่วยความจำค้าง (โดยเฉพาะอย่างยิ่ง IE11 ทำสิ่งนี้): คุณต้องแน่ใจว่าสำเนาทั้งหมดในหน่วยความจำถูกล้างก่อนที่จะรีเฟรชแคช HTTP หากรหัส javascript อื่น ๆ กำลังทำงานแบบอะซิงโครนัสคุณอาจต้องป้องกันไม่ให้โค้ดนั้นสร้างสำเนาของรูปภาพที่จะรีเฟรชในระหว่างนี้

  • โทรiframe.contentWindow.location.reload(true). trueบังคับบายพาสแคชโหลดโดยตรงจากเซิร์ฟเวอร์และเขียนทับสำเนาแคชที่มีอยู่

  • เมื่อการโหลดอีกครั้งเสร็จสิ้นให้เรียกคืนรูปภาพเปล่า ๆ ตอนนี้พวกเขาควรจะแสดงเวอร์ชั่นใหม่จากเซิร์ฟเวอร์!

สำหรับภาพโดเมนเดียวกันคุณสามารถโหลดภาพลงใน iframe ได้โดยตรง สำหรับภาพข้ามโดเมนคุณต้องแทนโหลดหน้าเว็บแบบ HTML จากโดเมนของคุณที่มีภาพใน<img>แท็กมิฉะนั้นคุณจะได้รับ "การเข้าถึงถูกปฏิเสธข้อผิดพลาด" iframe.contentWindow.reload(...)เมื่อพยายามที่จะเรียกร้อง

ข้อดี:ทำงานเหมือนฟังก์ชั่น image.reload () ที่คุณต้องการให้ DOM มี! อนุญาตให้ใช้รูปภาพโดยแคชตามปกติ (แม้จะมีวันหมดอายุในอนาคตหากคุณต้องการจึงหลีกเลี่ยงการตรวจสอบความถูกต้องบ่อยครั้ง) ช่วยให้คุณสามารถรีเฟรชภาพโดยไม่เปลี่ยน URL สำหรับภาพนั้นในหน้าปัจจุบันหรือในหน้าอื่น ๆ โดยใช้รหัสฝั่งไคลเอ็นต์เท่านั้น

ข้อด้อย:อาศัย Javascript ไม่รับประกัน 100% ว่าจะทำงานได้อย่างถูกต้องในทุกเบราว์เซอร์ (ฉันได้ทดสอบสิ่งนี้ใน FF27, Chrome33 และ IE11 เรียบร้อยแล้ว) ซับซ้อนมากเมื่อเทียบกับวิธีอื่น

เวลาใช้:เมื่อคุณมีคอลเลกชันของรูปภาพแบบคงที่โดยทั่วไปที่คุณต้องการเก็บไว้ แต่คุณยังคงต้องสามารถอัปเดตเป็นครั้งคราวและรับข้อเสนอแนะภาพทันทีที่การปรับปรุงเกิดขึ้น (โดยเฉพาะเมื่อรีเฟรชหน้าเบราว์เซอร์ทั้งหมดจะไม่ทำงานเหมือนในบางเว็บแอพที่สร้างบน AJAX) และเมื่อวิธีการ (1) - (3) เป็นไปไม่ได้เพราะ (ด้วยเหตุผลใดก็ตาม) คุณไม่สามารถเปลี่ยน URL ทั้งหมดที่อาจแสดงภาพที่คุณต้องการอัปเดต (โปรดทราบว่าการใช้ทั้ง 3 วิธีรูปภาพจะถูกรีเฟรช แต่หากหน้าอื่นพยายามแสดงรูปภาพนั้นโดยไม่ใช้ตัวคัดกรองหรือตัวระบุส่วนที่เหมาะสมมันอาจแสดงเวอร์ชันที่เก่ากว่าแทน)

รายละเอียดของการใช้สิ่งนี้ในลักษณะที่แข็งแกร่งและยืดหยุ่นได้รับดังต่อไปนี้:

สมมติว่าเว็บไซต์ของคุณมีพิกเซลว่างเปล่า 1x1 พิกเซล. ที่ 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) อาจต้องมีการเปลี่ยนแปลงจาวาสคริปต์ข้างต้นในกรณีเหล่านี้


ฉันชอบแนวคิดของวิธีที่ 4 แต่คุณไม่สามารถโหลดเนื้อหาภายนอกด้วย Iframe ได้ไหม ขณะนี้ฉันใช้วิธีที่ 3 ในแอปพลิเคชันเว็บหน้าเดียว แต่ฉันไม่ชอบความจริงที่ว่าคุณต้องโหลดทั้งหน้าใหม่เพื่อรับภาพใหม่แม้ว่า HTML ของเทมเพลตจะได้รับการโหลดซ้ำ
Emilios1995

@Emilios: ... นอกจากนี้ฉันไม่เข้าใจความคิดเห็นของคุณเกี่ยวกับการโหลดซ้ำทั้งหน้า สามารถใช้ทั้งสองวิธี (3) และ (4) ในจาวาสคริปต์ฝั่งไคลเอ็นต์โดยไม่ต้องโหลดซ้ำยกเว้นภาพเดียวที่คุณกำลังรีเฟรช สำหรับวิธีการ (3) ที่เพิ่งจะหมายถึงการใช้จาวาสคริปต์เพื่อเปลี่ยนคุณสมบัติ 'src' ของภาพจาก (เช่น)image.jpg#123เป็นimage.jpg#124(หรืออะไรก็ตามตราบใดที่บิตหลังจากการเปลี่ยนแปลง '#') คุณช่วยอธิบายให้ชัดเจนว่าคุณกำลังโหลดซ้ำอยู่ทำไมและทำไม?
Doin

@Emilios: คุณสามารถโหลดเนื้อหาภายนอก (ข้ามโดเมน) ไปยัง iframe ได้ ... แต่คุณไม่สามารถเข้าถึงได้contentWindowผ่านทาง javascript เพื่อทำreload(true)โทรซึ่งเป็นส่วนสำคัญของวิธีการ ... ดังนั้นไม่วิธี (4) ) จะไม่ทำงานสำหรับเนื้อหาข้ามโดเมน ด่างดี; ฉันจะอัปเดต "จุดด้อย" เพื่อรวมสิ่งนั้น
Doin

@Emilios: โอ๊ะโอไม่ฉันจะไม่: ฉันรู้ว่าการแก้ไขง่ายๆ (ตอนนี้รวมอยู่ในคำตอบของฉัน) ช่วยให้สามารถทำงานกับภาพข้ามโดเมนได้เช่นกัน (หากคุณสามารถวางสคริปต์ฝั่งเซิร์ฟเวอร์ไว้บนเซิร์ฟเวอร์ของคุณ)
Doin

@pseudosavant: น่าเสียดายที่ฉันสังเกตเห็นเพียงประมาณ 17 เดือนต่อมา แต่ฉันขอโทษที่ต้องบอกคุณว่าการแก้ไขรหัสของฉันไม่ดี (เพื่อความเป็นธรรมฉันไม่คิดว่ารหัสโทรกลับที่ฉันมีตอนแรกนั้นถูกต้องเช่นกัน) ตอนนี้ฉันเขียนตอนใหม่ (4) ทั้งคำอธิบายและรหัส โค้ดก่อนหน้าของคุณไม่เคยมีภาพเปล่า (ดังนั้นจึงอาจล้มเหลวในรูปแบบแปลก ๆ โดยเฉพาะใน IE และโดยเฉพาะอย่างยิ่งถ้าภาพนั้นปรากฏในหลาย ๆ ที่) แต่ยิ่งแย่กว่านั้นมันก็ลบ iframe ทันทีหลังจากเริ่มโหลดใหม่เต็มซึ่งหมายความว่า ทำงานเป็นระยะ ๆ หรือไม่ทำงานเลย ขออภัย!
Doin

185

เป็นทางเลือกแทน ...

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 เช่นกัน


1
ที่ดี! หลังจากพยายามโหลดรูปภาพบนเว็บของฉันซึ่งเต็มไปด้วยความล่าช้าฉันพยายามแก้ไขโดยใช้วิธีแก้ปัญหาของคุณ (ด้วย '#', การใช้ '?' ไม่ได้ผลสำหรับฉัน) ขอบคุณมาก!!!
user304602

18
มีแคชที่เกี่ยวข้องสองรายการที่นี่: มีแคช HTTP ปกติของเบราว์เซอร์และแคชในหน่วยความจำของรูปภาพที่แสดงเมื่อเร็ว ๆ นี้ แคชในหน่วยความจำหลังนี้ได้รับการทำดัชนีโดยแอsrcททริบิวต์แบบเต็มดังนั้นการเพิ่มตัวระบุแฟรกเมนต์เฉพาะเพื่อให้แน่ใจว่าภาพไม่ได้ถูกดึงออกมาจากหน่วยความจำ แต่ตัวระบุส่วนจะไม่ถูกส่งเป็นส่วนหนึ่งของคำขอ HTTP ดังนั้นแคช HTTP ปกติจะถูกใช้ตามปกติ นั่นเป็นเหตุผลที่เทคนิคนี้ใช้งานได้
Doin

มีหลายส่วนหัวแคช ที่จริงฉันไม่รู้ภาษาอังกฤษดีมากคุณช่วยบอกฉันหน่อยได้ไหมว่าฉันควรใช้อันไหน?! ฉันต้องการบางสิ่งที่ไม่ได้แคชเพียงภาพถ่ายที่มีการเปลี่ยนแปลง (เช่นแคปช่า) และแคชสิ่งอื่น ๆ จึงCache-Control: max-age=0, must-revalidateเป็นสิ่งที่ดีสำหรับฉันหรือไม่
Shafizadeh

มันไม่ทำงานสำหรับฉัน สิ่งเดียวที่แตกต่างกันในกรณีของฉันคือฉันมี URL ไปยังการดำเนินการควบคุมซึ่งดึง img จาก db ฉันมีข้อโต้แย้งอื่น ๆ สำหรับแอ็คชั่นคอนโทรลเลอร์ดังนั้นฉันจึงเพิ่มเป็น "...... & convert = true & t =" + new Date (). getTime (); และ "...... & conversion = true #" + new Date (). getTime () ;. มีอะไรที่ฉันทำผิดหรือเปล่า?
shaffooo

1
เพื่อหลีกเลี่ยงค่าใช้จ่ายในการสร้างวัตถุและ / หรือการเรียกเมธอดคุณสามารถใช้จำนวนเต็มที่เพิ่มขึ้นเป็น cache-buster:newImage.src = "http://localhost/image.jpg#" + i++;
laindir

7

หลังจากสร้างภาพใหม่คุณจะลบภาพเก่าออกจาก DOM และแทนที่ด้วยภาพใหม่หรือไม่

คุณสามารถคว้าภาพใหม่ ๆ ทุกครั้งที่อัปเดตการโทรภาพ แต่ไม่สามารถเพิ่มภาพเหล่านั้นในหน้า

มีหลายวิธีที่จะทำ บางสิ่งเช่นนี้จะได้ผล

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

หลังจากทำงานแล้วหากยังคงมีปัญหาน่าจะเป็นปัญหาแคชเหมือนคำตอบอื่น ๆ ที่พูดถึง


3

คำตอบหนึ่งคือแฮ็กเพิ่มพารามิเตอร์การสืบค้นบางอย่างเช่นได้รับการแนะนำ

คำตอบที่ดีกว่าคือการปล่อยสองตัวเลือกพิเศษในส่วนหัว HTTP ของคุณ

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

ด้วยการระบุวันที่ในอดีตเบราว์เซอร์จะไม่ถูกแคช Cache-Controlถูกเพิ่มเข้าไปใน HTTP / 1.1 และแท็กที่ต้องตรวจสอบใหม่บ่งชี้ว่าพร็อกซีไม่ควรแสดงภาพเก่าแม้จะอยู่ในสถานการณ์ที่ไม่เหมาะสมและPragma: no-cacheไม่จำเป็นสำหรับเบราว์เซอร์ / แคชสมัยใหม่ในปัจจุบัน แต่อาจช่วยแก้ไขปัญหาเก่า ๆ


3
ฟังดูเหมือนว่ามันจะใช้ได้ แต่ก็ยังคงแสดงภาพเหมือนเดิมแม้กับแฮ็ก ฉันจะเพิ่มข้อมูลส่วนหัวในคำถาม
QueueHammer

ฉันเพิ่งสังเกตเห็นว่าคุณกำลังรีเฟรชแท็ก img ซ้ำไปซ้ำมา เบราว์เซอร์อาจตรวจพบเมื่อคุณไปตั้งค่า src ที่ src ไม่ได้เปลี่ยนดังนั้นจึงไม่รบกวนการรีเฟรช (เนื่องจากการตรวจสอบนี้เกิดขึ้นที่ระดับ DOM และไม่มีส่วนเกี่ยวข้องกับเป้าหมาย) จะเกิดอะไรขึ้นถ้าคุณเพิ่ม "?" + หมายเลข - ไปยัง url ของรูปภาพที่ถูกเรียกคืนหรือไม่
Edward KMETT

3

ฉันมีความต้องการ: 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 ... คุณต้องเปลี่ยนเป็น onload-events ที่เหมาะสม


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

ด้านล่างในจาวาสคริปต์

<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 วินาที ฉันกำลังใช้สิ่งนี้ในหน้าเว็บที่มีกล้องรักษาความปลอดภัยหน้าแรกแบบต่างๆ


2

สิ่งที่ฉันทำลงไปคือให้เซิร์ฟเวอร์แมปคำขอรูปภาพใด ๆ ที่ไดเรกทอรีนั้นกับแหล่งที่ฉันพยายามอัปเดต จากนั้นฉันก็ให้ตัวจับเวลาของฉันผนวกหมายเลขลงท้ายชื่อเพื่อให้ 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);
}

8
สิ่งนี้จะมีปัญหาแบบเดียวกันกับการแคชอิมเมจหลายสำเนาเป็นโซลูชันการสอบถาม (Paolo และอื่น ๆ ) และต้องเปลี่ยนเซิร์ฟเวอร์
TomG

2

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')" />


3
โปรดอธิบายให้ OP ทราบว่าทำไมสิ่งนี้ถึงช่วยแทนการวางโค้ดได้เพียงเล็กน้อย
นาม

ฉันไม่คิดว่า../showImage.phpFri May 01 2015 17:34:18 GMT+0200 (Mitteleuropäische Sommerzeit)เป็นชื่อไฟล์ที่ถูกต้อง ... อย่างน้อยนี่คือสิ่งที่มันพยายามโหลด ...
ByteHamster

เปลี่ยนpath='../showImage.php';เป็นpath='../showImage.php?';
BOOMik

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

ตั้งค่า src ของตัวเองเป็น src ของมัน


1

ลองใช้การสอบถามที่ไม่มีค่าเพื่อทำให้เป็น 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);
}

เพิ่ม WQS ให้กับรหัสและตรวจสอบว่าคำขอได้รับการยอมรับและเบราว์เซอร์เห็นการตอบสนองที่มาจากที่อยู่ + WQS โดยไม่ต้องรีเฟรชภาพ
QueueHammer

1

ตามอย่างหนักใน Doin ของ # 4 รหัสด้านล่างเช่นช่วยลดความยุ่งยากรหัสที่บิตที่ดีใช้document.writeแทนsrc ในiframeการล ธ สนับสนุน นอกจากนี้ยังมุ่งเน้นไปที่การแคชเบราว์เซอร์ที่ไม่ได้โหลดซ้ำทุกภาพในหน้าเว็บ

ด้านล่างเขียนขึ้นtypescriptและใช้ไลบรารี่สัญญาangular $ qเพียงแค่ fyi แต่ควรง่ายพอที่จะย้ายไปยังวานิลลาจาวาสคริปต์ วิธีการมีความหมายที่จะอยู่ในชั้นเรียน 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;
    }

เพื่อป้องกันข้อบกพร่อง XSS คุณควรใช้+ encodeURI(src) +อย่างถูกต้องหลบหนีในsrc iframe
Tino

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')" />

downvoted เนื่องจากเป็นเพียงสำเนาของรหัส @ Mahmoud ที่ได้รับการแก้ไขเล็กน้อย แต่ในทางตรงกันข้ามนี่ไม่ได้ทำให้รูปภาพสดชื่น
Tino

0

ฉันแก้ไขปัญหานี้ด้วยการส่งข้อมูลกลับผ่าน servlet

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());

จากหน้าคุณเพียงให้ servlet กับ params เพื่อหยิบไฟล์ภาพที่ถูกต้อง

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

0

นี่คือทางออกของฉัน มันง่ายมาก การจัดตารางเฟรมน่าจะดีกว่า

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

0

ไม่จำเป็นต้องมีคนnew Date().getTime()เสฉวน คุณสามารถหลอกลวงเบราว์เซอร์โดยมีภาพจำลองที่มองไม่เห็นและใช้ jQuery .load () จากนั้นสร้างภาพใหม่ในแต่ละครั้ง:

<img src="" id="dummy", style="display:none;" />  <!-- dummy img -->
<div id="pic"></div>

<script type="text/javascript">
  var url = whatever;
  // You can repeat the following as often as you like with the same url
  $("#dummy").load(url);
  var image = new Image();
  image.src = url;
  $("#pic").html("").append(image);
</script>

0

วิธีแก้ปัญหาง่าย ๆ : เพิ่มหัวข้อนี้ในการตอบกลับ:

Cache-control: no-store

เหตุใดจึงมีการอธิบายงานนี้อย่างชัดเจนในหน้าสิทธิ์นี้: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control

นอกจากนี้ยังอธิบายว่าทำไมno-cacheไม่ทำงาน

คำตอบอื่น ๆ ไม่ทำงานเพราะ:

Caching.deleteเป็นเรื่องเกี่ยวกับแคชใหม่ที่คุณอาจสร้างขึ้นสำหรับการทำงานแบบออฟไลน์โปรดดู: https://web.dev/cache-api-quick-guide/

แฟรกเมนต์ที่ใช้ # ใน URL ไม่ทำงานเนื่องจาก # แจ้งให้เบราว์เซอร์ไม่ส่งการร้องขอไปยังเซิร์ฟเวอร์

แคชบัสเตอร์ที่มีส่วนที่เพิ่มแบบสุ่มใน url ทำงาน แต่จะเติมแคชของเบราว์เซอร์ด้วย ในแอพของฉันฉันต้องการดาวน์โหลดรูปภาพขนาด 5 MB ทุกสองสามวินาทีจากเว็บแคม จะใช้เวลาเพียงหนึ่งชั่วโมงหรือน้อยกว่านั้นเพื่อทำให้พีซีของคุณหยุดการทำงานอย่างสมบูรณ์ ฉันยังไม่รู้ว่าทำไมแคชของเบราว์เซอร์ไม่ได้ถูก จำกัด ให้อยู่ในระดับที่เหมาะสม แต่นี่เป็นข้อเสียอย่างแน่นอน


0

ฉันปรับปรุงสคริปต์จากAlexMAเพื่อแสดงเว็บแคมของฉันบนหน้าเว็บที่อัปโหลดภาพใหม่ด้วยชื่อเดียวกันเป็นระยะ ฉันมีปัญหาที่บางครั้งภาพกะพริบเนื่องจากภาพที่เสียหายหรือภาพที่โหลดไม่สมบูรณ์ (ขึ้น) เพื่อป้องกันการกะพริบฉันตรวจสอบความสูงตามธรรมชาติของภาพเนื่องจากขนาดของภาพเว็บแคมของฉันไม่เปลี่ยนแปลง เฉพาะในกรณีที่ความสูงของภาพที่โหลดเข้ากับความสูงของภาพต้นฉบับภาพเต็มจะปรากฏบนหน้าเว็บ

  <h3>Webcam</h3>
  <p align="center">
    <img id="webcam" title="Webcam" onload="updateImage();" src="https://www.your-domain.com/webcam/current.jpg" alt="webcam image" width="900" border="0" />

    <script type="text/javascript" language="JavaScript">

    // off-screen image to preload next image
    var newImage = new Image();
    newImage.src = "https://www.your-domain.com/webcam/current.jpg";

    // remember the image height to prevent showing broken images
    var height = newImage.naturalHeight;

    function updateImage()
    {
        // for sure if the first image was a broken image
        if(newImage.naturalHeight > height)
        {
          height = newImage.naturalHeight;
        }

        // off-screen image loaded and the image was not broken
        if(newImage.complete && newImage.naturalHeight == height) 
        {
          // show the preloaded image on page
          document.getElementById("webcam").src = newImage.src;
        }

        // preload next image with cachebreaker
        newImage.src = "https://www.your-domain.com/webcam/current.jpg?time=" + new Date().getTime();

        // refresh image (set the refresh interval to half of webcam refresh, 
        // in my case the webcam refreshes every 5 seconds)
        setTimeout(updateImage, 2500);
    }

    </script>
</p>

-3

ฉันใช้แนวคิดด้านล่างของการเชื่อมรูปภาพเป็นครั้งแรกด้วย url (บัฟเฟอร์) ที่เป็นเท็จและถัดไปผูกกับ URL ที่ถูกต้อง

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

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

ด้วยวิธีนี้ฉันกำลังบังคับให้เบราว์เซอร์รีเฟรชด้วย URL ที่ถูกต้อง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.