일부 이미지에 대해 캐시 비활성화


113

PHP lib를 사용하여 이미지를 생성합니다.

때때로 브라우저는 새로 생성 된 파일을로드하지 않습니다.

내가 동적으로 생성 한 이미지에 대해서만 캐시를 비활성화하려면 어떻게해야합니까?

참고 : 시간이 지남에 따라 생성 된 이미지에 동일한 이름을 사용해야합니다.

답변:


233

해킹처럼 느껴지지만 이식성이 뛰어난이 문제에 대한 일반적이고 간단한 해결책은 동적 이미지에 대한 각 요청에 무작위로 생성 된 쿼리 문자열을 추가하는 것입니다.

예를 들어-

<img src="image.png" />

될 것이다

<img src="image.png?dummy=8484744" />

또는

<img src="image.png?dummy=371662" />

웹 서버 관점에서는 동일한 파일에 액세스하지만 브라우저 관점에서는 캐싱을 수행 할 수 없습니다.

난수 생성은 페이지를 제공 할 때 서버 (페이지 자체가 캐시되지 않았는지 확인) 또는 클라이언트 (JavaScript 사용)에서 발생할 수 있습니다.

웹 서버가이 트릭에 대처할 수 있는지 확인해야합니다.


87
난수 대신 데이터가 변경된 타임 스탬프 또는 반영된 데이터의 버전 번호를 사용합니다.
lhunath 2009


19
참고 : 실제로 브라우저가 이미지를 캐싱하는 것을 막는 것이 아니라 캐시 된 이미지를 보는 것을 막을뿐입니다. 이미지에 적절한 헤더를 적용하는 것이 가장 좋은 방법입니다 (아래 lhunath 솔루션 참조). 이 방법으로 캐시를 불필요하게 이미지로 채우므로 실제로 캐시하려는 항목에 대해 캐시 공간을 줄이는 비용으로 캐시하지 않으려 고합니다.
Jos

나는 이 기사 가 그러한 행동의 이유를 설명 한다고 믿는다 .
Metalcoder 2013-10-03

1
실제로 작동하지 않습니다. 이미지를 다른 방식으로 플러시해야합니다 (일반적으로 이미지 자르기시 이미지는 동일하게
Ben

44

브라우저 캐싱 전략은 HTTP 헤더로 제어 할 수 있습니다. 그들은 단지 힌트 일 뿐이라는 것을 기억하십시오. 브라우저는이 필드와 다른 필드에서 매우 일관성이 없기 때문에 다양한 브라우저에서 원하는 효과를 얻으려면 여러 헤더가 필요합니다.

header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");

1
이것은 전체 페이지에 적용됩니다 .... 하나의 이미지 (해당 페이지의 특정 이미지)에 대해서만 캐시를 비활성화 할 수 없습니까?
dole doug

5
@Thorpe : HTTP 응답에 적용됩니다. 응답에 포함 된 내용은 관련이 없습니다. 이미지 데이터, HTML 데이터 또는 그 밖의 모든 것입니다. 작동하지 않았다면 아마도 제대로하지 않았을 것입니다. 응답의 HTTP 헤더를 확인하여 올바르게 할당되었는지 확인하십시오.
lhunath

이게 효과가 있었으면 좋겠는데 ... Chrome에는 문제가 없지만 Firefox 14 및 IE 8은 위의 헤더가 전송 되어도 이미지 새로 고침을 거부합니다. 이것은 쿼리 문자열에 임의의 매개 변수를 추가하는 것보다 훨씬 더 깨끗한 솔루션이었을 것입니다. 한숨
Pawel Krakowiak

2
@PawelKrakowiak 이미 캐시 된 이미지에는 헤더를 추가해도 작동 하지 않습니다. 브라우저가 서버에 요청조차하지 않아 헤더를 볼 수 없기 때문입니다. 추가 한 이미지 요청에 대해 작동합니다.
lhunath

2
이 솔루션은 웹 디자이너가 아닌 프로그래머를위한 것입니다. 나는 그들이 프로그래밍 언어로 이미지를 생성하지 않는 한 이미지를 열고 이미지를 만들고 헤더를 추가 할 수 없기 때문에 지적 할 것이라고 생각했습니다.
Bruce

13

자바 스크립트를 사용하여 브라우저에서 동적으로 수행해야하는 경우 다음 예가 있습니다.

<img id=graph alt="" 
  src="http://www.kitco.com/images/live/gold.gif" 
  />

<script language="javascript" type="text/javascript">
    var d = new Date(); 
    document.getElementById("graph").src = 
      "http://www.kitco.com/images/live/gold.gif?ver=" + 
       d.getTime();
</script>

12

솔루션 1은 좋지 않습니다. 작동하지만 이미지 파일 끝에 해키 랜덤 또는 타임 스탬프 쿼리 문자열을 추가하면 이미지가 변경되었는지 여부에 관계없이 페이지가로드 될 때마다 브라우저가 모든 이미지의 모든 버전을 다시 다운로드하고 캐시합니다. 서버에서.

솔루션 2는 쓸모가 없습니다. nocache이미지 파일에 헤더를 추가 하는 것은 구현하기가 매우 어려울뿐만 아니라 미래의 어느 시점에서 변경 수 있다고 생각되는 이미지를 처음로드 할 때 미리 필요한시기예측 해야하기 때문에 완전히 비실용적 입니다. .

Etags 입력 ...

이 문제를 해결하는 가장 좋은 방법 은 이미지 디렉토리 의 .htaccess 파일 내에서 ETAGS 를 사용 하는 것 입니다. 다음은 Apache에게 이미지 파일 헤더의 브라우저에 고유 한 해시를 보내도록 지시합니다. 이 해시는 이미지 파일이 수정 될 때만 변경되며이 변경은 브라우저가 다음에 이미지를 요청할 때 이미지를 다시로드하도록 트리거합니다.

<FilesMatch "\.(jpg|jpeg)$">
FileETag MTime Size
</FilesMatch>

11

나는 모든 대답을 확인했고 가장 좋은 것은 (그렇지 않은) 것 같았습니다.

<img src="image.png?cache=none">

처음에.

그러나 cache = none 을 추가하면 매개 변수 (정적 "none"단어)를 추가하면 아무 영향도주지 않고 브라우저는 여전히 캐시에서로드됩니다.

이 문제에 대한 해결책은 다음과 같습니다.

<img src="image.png?nocache=<?php echo time(); ?>">

기본적으로 유닉스 타임 스탬프를 추가하여 매개 변수를 동적으로 만들고 캐시없이 만들었습니다.

그러나 내 문제는 약간 달랐습니다. 즉석에서 생성 된 PHP 차트 이미지를로드하고 $ _GET 매개 변수로 페이지를 제어했습니다. URL GET 매개 변수가 동일하게 유지 될 때 캐시에서 이미지를 읽고 GET 매개 변수가 변경 될 때 캐시하지 않기를 원했습니다.

이 문제를 해결하려면 $ _GET을 해시해야했지만 여기에 배열이기 때문에 해결책이 있습니다.

$chart_hash = md5(implode('-', $_GET));
echo "<img src='/images/mychart.png?hash=$chart_hash'>";

편집하다 :

위의 솔루션은 잘 작동하지만 파일이 변경 될 때까지 캐시 된 버전을 제공하고 싶을 때가 있습니다. (위의 솔루션을 사용하면 해당 이미지에 대한 캐시가 완전히 비활성화됩니다.) 따라서 브라우저에서 캐시 된 이미지를 제공하려면 이미지 파일 사용이 변경 될 때까지 다음과 같이하십시오.

echo "<img src='/images/mychart.png?hash=" . filemtime('mychart.png') . "'>";

filemtime ()은 파일 수정 시간을 가져옵니다.


4

이 주제가 오래되었다는 것을 알고 있지만 Google에서 순위가 ​​매우 높습니다. 나는 이것을 헤더에 넣는 것이 잘 작동한다는 것을 알았습니다.

<meta Http-Equiv="Cache-Control" Content="no-cache">
<meta Http-Equiv="Pragma" Content="no-cache">
<meta Http-Equiv="Expires" Content="0">
<meta Http-Equiv="Pragma-directive: no-cache">
<meta Http-Equiv="Cache-directive: no-cache">

안타깝게도 최신 브라우저는 이러한 지시문을 무시하고 있습니다. 따라서이 솔루션은 일부 브라우저에서만 작동 할 수 있으며 특정 이미지뿐만 아니라 모든 것에 대해 캐시를 비활성화합니다
ZioCain

4

나는 이것에 대한 해결책을 찾고 있었고 위의 대답은 내 경우에는 효과가 없었습니다 (그리고 그들에 대해 언급할만한 평판이 충분하지 않습니다). 적어도 내 사용 사례와 내가 사용하고있는 브라우저 (OSX의 Chrome)에서 캐싱을 막는 유일한 방법은 다음과 같습니다.

Cache-Control = 'no-store'

완전성을 위해 저는 이제 'no-cache, no-store, must-revalidate'3 가지를 모두 사용하고 있습니다.

그래서 제 경우에는 (Python의 Flask에서 동적으로 생성 된 이미지를 제공) 가능한 한 많은 브라우저에서 작업하기 위해 다음을 수행해야했습니다.

def make_uncached_response(inFile):
    response = make_response(inFile)
    response.headers['Pragma-Directive'] = 'no-cache'
    response.headers['Cache-Directive'] = 'no-cache'
    response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
    response.headers['Pragma'] = 'no-cache'
    response.headers['Expires'] = '0'
    return response

그냥 응답에는 매장을 가하고되지는 나를 위해 일하기가 충분했다
scourge192

Chrome뿐만 아니라 Firefox에서도 마찬가지입니다. 이제 표준으로 보입니다 : developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control ( " 캐싱 방지 "섹션 참조).
Gino Mempin 19.11.21

3

이미지 소스를 변경하는 것이 해결책입니다. 이미지에 타임 스탬프 또는 난수를 추가하여 실제로이를 수행 할 수 있습니다.

예를 들어 이미지가 나타내는 데이터의 체크섬을 추가하는 것이 좋습니다. 이것은 가능한 경우 캐싱을 가능하게합니다.


1

무리에 다른 솔루션 하나를 추가합시다.

끝에 고유 한 문자열을 추가하는 것은 완벽한 솔루션입니다.

example.jpg?646413154

다음 솔루션은이 방법을 확장하고 캐싱 기능을 제공하고 이미지가 업데이트 될 때 새 버전을 가져옵니다.

이미지가 업데이트되면 filemtime 이 변경됩니다.

<?php
$filename = "path/to/images/example.jpg";
$filemtime = filemtime($filename);
?>

이제 이미지를 출력합니다.

<img src="images/example.jpg?<?php echo $filemtime; ?>" >

1
그것이 캐싱 유효성 때문에 내가 사용한 것입니다.
유전자

1

나는이 문제가 있었고 이렇게 극복했습니다.

var newtags='<div class="addedimage"><h5>preview image</h5><img src="'+one+'?nocache='+Math.floor(Math.random() * 1000)+'"></div>';

0

비슷한 문제를 해결하기 위해 이것을 사용했습니다 ... (외부 공급자로부터) 이미지 카운터를 표시합니다. 항상 올바르게 새로 고침되지 않았습니다. 그리고 임의의 매개 변수가 추가 된 후에는 모두 잘 작동합니다. :)

적어도 1 분마다 새로 고침 할 수 있도록 날짜 문자열을 추가했습니다.

샘플 코드 (PHP) :

$output .= "<img src=\"http://xy.somecounter.com/?id=1234567890&".date(ymdHi)."\" alt=\"somecounter.com\" style=\"border:none;\">";

그 결과 src다음과 같은 링크가 생성됩니다.

http://xy.somecounter.com/?id=1234567890&1207241014

0

하드 코딩 된 이미지 URL이있는 경우 (예 : http://example.com/image.jpg) php를 사용하여 이미지에 헤더를 추가 할 수 있습니다.

먼저 아파치가 jpg를 php로 처리하도록해야합니다. 여기를보십시오 : 확장자 file.php.jpg로 PHP를 실행할 수 있습니까?

파일에서 이미지 (imagecreatefromjpeg)를로드 한 다음 이전 답변의 헤더를 추가합니다. php 함수 헤더를 사용하여 헤더를 추가하십시오.

그런 다음 imagejpeg 함수로 이미지를 출력합니다.

PHP가 jpg 이미지를 처리하도록하는 것은 매우 안전하지 않습니다. 또한이 솔루션을 테스트하지 않았으므로 작동하도록하는 것은 귀하에게 달려 있습니다.


-1

간단하고 하나의 헤더 위치를 보냅니다.

내 사이트에는 하나의 이미지가 포함되어 있으며 이미지를 업로드 한 후 변경되지 않고 다음 코드를 추가합니다.

<?php header("Location: pagelocalimage.php"); ?>

나를위한 일입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.