2012-06-01 2 views
11

? img = 매개 변수로 호출되는 PHP 스크립트가 있습니다.처리 PHP 스크립트의 If-modified-since 헤더

해당 매개 변수의 값은 이미지의 (URL 인코딩 된) URL입니다.

내 스크립트가 이미 내 서버에 저장되어 있는지 확인합니다.

그렇지 않으면 다운로드합니다. 이 선택적으로 이미지 크기를 조정하고 콘텐츠 형식마지막으로 수정 된 헤더 앞에 추가 요청 브라우저로 즉 다시, STDOUT에 전송하는 후 :

이 일부 플래시를 해결하는 데 필요한
Connection:close 
Content-Type:image/jpeg 
Date:Fri, 01 Jun 2012 08:28:30 GMT 
Last-Modified:Fri, 01 Jun 2012 08:02:44 GMT 
Server:Apache/2.2.15 (CentOS) 
Transfer-Encoding:chunked 
X-Powered-By:PHP/5.3.3 

/crossdomain.xml이 문제와는 한 해 동안 때문에 나를 위해 잘 작동합니다 :

enter image description here

그러나 내가 들어오는 을 처리 할 수있는 기능을 추가하려면 - 수정 - 이후 헤더 - 을 보내지 않음 304 응답.

내 질문은 : 아파치에서 실행할 때

1), PHP에 있다고도 할 수 있습니까?

2) PHP에서 날짜를 가장 잘 처리 (예 : 구문 분석 및 생성)하는 방법은 무엇입니까?

보너스 질문) 콘텐츠 길이 헤더를 크기 조정 된 이미지에 추가하는 방법은 무엇입니까?

내 코드 (I 생략 한 CURL-다운로드 부분) 다음과 같습니다 :

<?php 

define('CACHE_DIR', '/var/www/cached_avatars/'); 

$img = urldecode($_GET['img']); 
$cached = CACHE_DIR . md5($img); 

# omitted downloading part for brevity 

$readfh = fopen($cached, 'rb'); 
if ($readfh) { 
     flock($readfh, LOCK_SH); 

     $size = getimagesize($cached); 
     $w = $size[0]; 
     $h = $size[1]; 
     $type = $size[2]; 
     $mime = $size['mime']; 

     # find the downscale factor to fit image into $maxw x $maxh 
     $scale = max($w/$maxw, $h/$maxh); 

     header('Content-Type: ' . $size['mime']); 
     header('Last-Modified: ' . gmdate('D, d M Y H:i:s T', filemtime($cached))); 

     $length = filesize($cached); 
     $buf = fread($readfh, $length); 
     fclose($readfh); 

     # the image is smaller than $maxw x $maxh, do not scale up 
     if ($scale <= 1) { 
       header('Content-Length: ' . $length); 
       print($buf); 
       return; 
     } 

     $tw = $w/$scale; 
     $th = $h/$scale; 
     $image = imagecreatefromstring($buf); 
     $thumb = imagecreatetruecolor($tw, $th); 
     imagecopyresampled($thumb, $image, 0, 0, 0, 0, $tw, $th, $w, $h); 
     imagedestroy($image); 

     # How to add Content-Length here, after image resizing? 

     if (IMAGETYPE_JPEG == $type) 
       imagejpeg($thumb, null, 75); 
     else if (IMAGETYPE_PNG == $type) 
       imagepng($thumb, null, 9); 
     else if (IMAGETYPE_GIF == $type) 
       imagegif($thumb, null); 

     imagedestroy($thumb); 
} 

?> 

난 그냥 좋은 포인터 또는 코드 조각을 요청, 나를 위해 내 일을하는 사람을 요구하고 있지 않다 - 필자는 아직 PHP의 영역 (헤더 + 날짜)에 대한 경험이 없기 때문에.

답변

35

이것은 PHP로 가능합니다!

브라우저가 수정 사항을 확인하면 If-Modified-Since 헤더를 보냅니다. PHP에서이 값은 $_SERVER['HTTP_IF_MODIFIED_SINCE'] 안에 설정됩니다.

그래서 (내가 믿는 RFC822을 사용하여 인코딩), 당신은 그냥 사용할 수 있습니다 strtotime() 날짜/시간 값을 해독하려면

if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && 
    strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= filemtime($localFileName)) 
{ 
    header('HTTP/1.0 304 Not Modified'); 
    exit; 
} 

설명을 다음 If-Modified-Since 헤더가 브라우저 및 날짜/시간을 기준으로 전송되는 경우 적어도 수정 한 날짜의 파일을 제공하는 경우 "304 Not Modified"헤더를 작성하고 중지하십시오.

그렇지 않으면 스크립트가 정상적으로 계속됩니다.

+1

도움이된다면 유효성을 검사하고 3 가지 형식을 모두 다루는 HTTP 날짜에 대해이 파서를 작성했습니다. https://github.com/evert/SabreDAV/blob/master/lib/Sabre/HTTP/Util.php#L23 – Evert

+1

감사합니다 모두,이 작품과 나는 문자열을 비교하는 대신에 날짜를 구문 분석 - 내 경우에 잘 작동하는 것 같습니다 : '$ mod = gmdate ('D, d MYH : i : s T', filemtime ($ 캐시 된)); if (@ $ _ SERVER [ 'HTTP_IF_MODIFIED_SINCE'] == $ mod) {header ('HTTP/1.0 304 Not Modified'); 출구; }' –

+0

@ Ja͢ck 어떻게 bash 나 C99에서 Ican을 사용할 수 있습니까? – user2284570

3

최근 등록 된 사용자 만 이미지를 볼 수있게하려면이 기능 (PHP로 이미지 제공)을 사용해야했습니다. Jack의 코드가 도움이되었지만 완벽하게 작동하려면 몇 가지 해킹을해야했습니다. 나는 이것을 공유해야한다고 생각했다.이 브라우저 요청 HTTP_IF_MODIFIED_SINCE의 경우 짧은에서

if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && 
    strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= filemtime($path_to_image)) 
{ 
    header('HTTP/1.0 304 Not Modified'); 
    header("Cache-Control: max-age=12096000, public"); 
    header("Expires: Sat, 26 Jul 2015 05:00:00 GMT"); 
    header("Pragma: cache"); 
    exit; 
}else{ 
    header("Content-type: image/jpeg"); 
    header("Cache-Control: max-age=12096000, public"); 
    header("Expires: Sat, 26 Jul 2015 05:00:00 GMT"); 
    header("Pragma: cache"); 
    echo file_get_contents($path_to_image); 
} 

이 스크립트는 수정되지 반환합니다. 그렇지 않으면 이미지에 적절한 헤더 및 만료 날짜가 표시됩니다.