Content-Length header が送信されない
PHPからzipファイルなどを読み込んで出力する際に Content-Length header を送信しておくと、ブラウザ側でダウンロードの進捗が表示されてユーザーにとって親切だと思う。
しかし、以下のPHPファイルを
<?php
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="a.zip"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize('a.zip'));
readfile('a.zip');
?>
実行するも LiveHTTPHeaders で確認するとヘッダーが
HTTP/1.x 200 OK
Date: Thu, 28 Jan 2010 08:09:10 GMT
Server: Apache
Content-Disposition: attachment; filename="a.zip"
Content-Transfer-Encoding: binary
Vary: Accept-Encoding
Content-Encoding: gzip
Keep-Alive: timeout=4, max=48
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/octet-stream
となり、Content-Length header が出力されていない。もちろんブラウザでの進捗も表示されない。
調べた結果、Apache の mod_deflate (mod_gzip) が導入されているのが原因であった。
そこで、先述のPHPを以下のように変更することで対応できる。
<?php
apache_setenv('no-gzip', '1'); // ← apache環境変数に deflate(gzip) 無効をセット
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="a.zip"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize('a.zip'));
readfile('a.zip');
?>
ヘッダーも
HTTP/1.x 200 OK
Date: Thu, 28 Jan 2010 08:09:10 GMT
Server: Apache
Content-Disposition: attachment; filename="a.zip"
Content-Transfer-Encoding: binary
Content-Length: 4774298
Keep-Alive: timeout=4, max=48
Connection: Keep-Alive
Content-Type: application/octet-stream
に変わり、ブラウザの進捗も表示された。
しかし、以下のPHPファイルを
<?php
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="a.zip"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize('a.zip'));
readfile('a.zip');
?>
実行するも LiveHTTPHeaders で確認するとヘッダーが
HTTP/1.x 200 OK
Date: Thu, 28 Jan 2010 08:09:10 GMT
Server: Apache
Content-Disposition: attachment; filename="a.zip"
Content-Transfer-Encoding: binary
Vary: Accept-Encoding
Content-Encoding: gzip
Keep-Alive: timeout=4, max=48
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/octet-stream
となり、Content-Length header が出力されていない。もちろんブラウザでの進捗も表示されない。
調べた結果、Apache の mod_deflate (mod_gzip) が導入されているのが原因であった。
そこで、先述のPHPを以下のように変更することで対応できる。
<?php
apache_setenv('no-gzip', '1'); // ← apache環境変数に deflate(gzip) 無効をセット
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="a.zip"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize('a.zip'));
readfile('a.zip');
?>
ヘッダーも
HTTP/1.x 200 OK
Date: Thu, 28 Jan 2010 08:09:10 GMT
Server: Apache
Content-Disposition: attachment; filename="a.zip"
Content-Transfer-Encoding: binary
Content-Length: 4774298
Keep-Alive: timeout=4, max=48
Connection: Keep-Alive
Content-Type: application/octet-stream
に変わり、ブラウザの進捗も表示された。