Domanda

In questo momento sto cercando di fornire file CSS e JS da un server che non mi consente di abilitare mod_gzip o mod_deflate . Quindi ho scritto un piccolo script PHP da comprimere con GZIP e tornare all'utente.

Codice di esempio:

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

Al momento sto riscontrando due problemi. Il primo è che sto riscontrando problemi nel determinare la dimensione risultante del file compresso per informare il browser della lunghezza del contenuto. Normalmente, includerei questa riga:

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

Ma, se lo faccio, il browser si blocca durante il tentativo di attendere ulteriori dati. C'è un modo per calcolare la dimensione totale? O dovrei ignorare questa direttiva dell'intestazione.

L'altro problema è, ogni volta che visualizzo questo file PHP in Firefox, prova a farmi scaricare il risultato. In Chrome, lo mostra semplicemente come mi aspetterei. Qualche suggerimento?

Modifica: Grazie a SoapBox, ho sostituito la fine del codice con questa:

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

Funziona benissimo per la lunghezza dei contenuti! Ma sto ancora facendo in modo che Firefox scarichi il file anziché visualizzarlo. : (

Modifica di nuovo: ecco il codice di fine codice modificato, per gentile concessione di Cletus.

// Start buffered output
ob_start();
// Check for gzip capability
if (stripos(

In questo momento sto cercando di fornire file CSS e JS da un server che non mi consente di abilitare mod_gzip o mod_deflate . Quindi ho scritto un piccolo script PHP da comprimere con GZIP e tornare all'utente.

Codice di esempio:

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

Al momento sto riscontrando due problemi. Il primo è che sto riscontrando problemi nel determinare la dimensione risultante del file compresso per informare il browser della lunghezza del contenuto. Normalmente, includerei questa riga:

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

Ma, se lo faccio, il browser si blocca durante il tentativo di attendere ulteriori dati. C'è un modo per calcolare la dimensione totale? O dovrei ignorare questa direttiva dell'intestazione.

L'altro problema è, ogni volta che visualizzo questo file PHP in Firefox, prova a farmi scaricare il risultato. In Chrome, lo mostra semplicemente come mi aspetterei. Qualche suggerimento?

Modifica: Grazie a SoapBox, ho sostituito la fine del codice con questa:

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

Funziona benissimo per la lunghezza dei contenuti! Ma sto ancora facendo in modo che Firefox scarichi il file anziché visualizzarlo. : (

Modifica di nuovo: ecco il codice di fine codice modificato, per gentile concessione di Cletus.

<*>

Inizierò una nuova domanda per capire perché Firefox continua a provare a scaricare il file.

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

Inizierò una nuova domanda per capire perché Firefox continua a provare a scaricare il file.

È stato utile?

Soluzione

Il problema qui è che per conoscere la lunghezza del contenuto devi sapere se il client supporta la codifica gzip e hai delegato quella decisione usando ob_gzhandler. Da Intestazioni 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

Versione completa:

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

Questo è molto meglio che affrontare il problema della codifica gzip da soli.

Altri suggerimenti

Devi prima fare l'intero gzip e misurare il risultato (o mantenendo i contenuti in memoria, o scrivendoli sul disco mentre comprimi e poi stating il file gzip), quindi scrivi l'intestazione Content-Length e poi invia il contenuto del file.

Oppure usa codifica di trasferimento chunked .

Per risolvere il problema di Firefox, penso che sia necessario includere header (" Content-Encoding: gzip "); in modo che il browser sappia decomprimere il contenuto.

Per quanto riguarda la lunghezza del contenuto, puoi provare a lasciare questo valore disattivato o provare a trovare un modo per usare " Transfer-Encoding: chunked " (non è possibile inviare questa intestazione, è necessario formattare i dati appositamente per essa). È possibile che ob_end_flush abiliti automaticamente il chunking.

Ti consiglio di ottenere WireShark e acquisire ciò che lo script php sta inviando e confrontarlo con un server che si comporta correttamente per vedere quali intestazioni, ecc. mancano.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top