문제

지금은 서버에서 CSS 및 JS 파일을 제공하려고 노력하고 있습니다. mod_gzip 또는 mod_deflate. 그래서 나는 GZIP로 압축하고 사용자에게 돌아가기 위해 작은 PHP 스크립트를 작성했습니다.

예제 코드 :

$filename = "style.css";

if (!file_exists($filename) || !($info = stat($filename))) {
  header("HTTP/1.1 404 Not Found");
  die();
}

header("Date: ".gmdate("D, j M Y H:i:s e", time()));
header("Cache-Control: max-age=2592000");
header("Last-Modified: ".gmdate("D, j M Y H:i:s e", $info['mtime']));
header("Etag: ".sprintf("\"%x-%x-%x\"", $info['ino'], $info['size'], $info['mtime']));
header("Accept-Ranges: bytes");
header("Cache-Control: Expires ".gmdate("D, j M Y H:i:s e", $info['mtime']+2592000));
header("Content-Type: text/html");

ob_start("ob_gzhandler");
echo file_get_contents($filename);
ob_end_flush();

지금 두 가지 문제가 있습니다. 첫 번째는, 컨텐츠 길이의 브라우저에 알리기 위해 압축 파일의 결과 크기를 결정하는 데 어려움이 있습니다. 일반적 으로이 줄을 포함시킬 것입니다.

header("Content-Length: ".$info["size"]);

그러나 만약 그렇다면 더 많은 데이터를 기다리려고 노력하면서 브라우저가 매달려 있습니다. 총 크기를 계산하는 방법이 있습니까? 또는이 헤더 지침을 무시해야합니다.

다른 문제는 Firefox 에서이 PHP 파일을 볼 때마다 결과를 다운로드하려고합니다. Chrome에서는 내가 기대할 수있는 것처럼 표시됩니다. 제안이 있습니까?

편집하다: SOAPBox 덕분에 코드의 끝을 다음과 같이 대체했습니다.

header("Content-Encoding: gzip");
$compressed = gzencode(file_get_contents($filename), 5);
header("Content-Length: ".strlen($compressed));
die($compressed);

이것은 컨텐츠 길이에 적합합니다! 그러나 나는 여전히 파일을 표시하는 대신 파일을 다운로드 할 Firefox를 얻고 있습니다. :(

다시 편집 : 다음은 Cletus가 제공하는 수정 된 코드 코드 코드입니다.

// Start buffered output
ob_start();
// Check for gzip capability
if (stripos($_SERVER['HTTP_ACCEPT_ENCODING'], "gzip") !== false) {
  ob_start("ob_gzhandler");
  echo file_get_contents($filename);
  ob_end_flush();
} else
  echo file_get_contents($filename);

// Write the content length
header('Content-Length: '.ob_get_length());
ob_end_flush();

Firefox가 파일을 계속 다운로드하려고하는 이유를 알아 내기 위해 새로운 질문을 시작할 것입니다.

도움이 되었습니까?

해결책

여기서 문제는 콘텐츠 길이를 알아야한다는 것입니다. 클라이언트가 GZIP 인코딩을 지원하는지 여부를 알아야하며 OB_GZHANDLER를 사용하여 해당 결정을 위임 한 것입니다. 에서 HTTP 헤더:

ob_start();
ob_start('ob_gzhandler');

  ... output the page content...

ob_end_flush();  // The ob_gzhandler one

header('Content-Length: '.ob_get_length());

ob_end_flush();  // The main one

완전한 버전 :

$filename = "style.css";

if (!file_exists($filename) || !($info = stat($filename))) {
  header("HTTP/1.1 404 Not Found");
  die();
}

header("Date: ".gmdate("D, j M Y H:i:s e", time()));
header("Cache-Control: max-age=2592000");
header("Last-Modified: ".gmdate("D, j M Y H:i:s e", $info['mtime']));
header("ETag: ".sprintf("\"%x-%x-%x\"", $info['ino'], $info['size'], $info['mtime']));
header("Accept-Ranges: bytes");
header("Expires: ".gmdate("D, j M Y H:i:s e", $info['mtime']+2592000));
header("Content-Type: text/css"); // note: this was text/html for some reason?

ob_start();
ob_start("ob_gzhandler");
echo file_get_contents($filename);
ob_end_flush();
header('Content-Length: '.ob_get_length());
ob_end_flush();

이것은 많이 GZIP 인코딩 문제를 직접 복용하는 것보다 낫습니다.

다른 팁

먼저 전체 GZIP를 수행하고 결과를 측정해야합니다 (내용을 메모리에 고정하거나 압축 할 때 디스크에 쓰기 한 다음 GZIPPED 파일을 통계) 한 다음 컨텐츠 길이 헤더를 작성한 다음 파일을 보냅니다. 내용물.

또는 사용 청크 전송 인코딩.

Firefox 문제를 해결하려면 header( "Content-Encoding: gzip" ); 브라우저가 컨텐츠를 압축하는 것을 알고 있습니다.

컨텐츠 길이는이 값을 꺼내거나 "전송 인코딩 : 청크"를 사용하는 방법을 찾으려고 시도 할 수 있습니다 (JSUT이 헤더를 보낼 수 없으므로 데이터를 특별히 포맷해야합니다. ). 가능합니다 ob_end_flush 청킹을 자동으로 활성화합니다.

Wireshark를 얻고 PHP 스크립트가 보내는 것을 캡처하고 올바르게 작동하는 서버와 비교하여 누락 된 헤더 등을 확인하는 것이 좋습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top