質問
次のコードを使用してディレクトリからzipファイルを作成し、httpダウンロード経由でユーザーに提供しようとしています。
// write the file
file_put_contents($path . "/index.html", $output);
// zip up the contents
chdir($path);
exec("zip -r {$course->name} ./");
$filename = "{$course->name}.zip";
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' .urlencode($filename));
header('Content-Transfer-Encoding: binary');
readfile($filename);
zipファイルを作成することはできますが、httpでダウンロードすることはできません。 FTPクライアントを使用して作成されたzipファイルをダウンロードすると、MacのStuffit Expanderはファイルを正常に解凍しますが、httpでダウンロードすると、mac unzipは無限ループを作成します。つまり、ダウンロードしたファイルはcourse.zipと呼ばれ、ファイルを解凍するとcourse.zip.cpgzが得られ、そのファイルを解凍すると再びcourse.zipが得られるということです。
アイデアはありますか?
ありがとう!
解決
-
要求されるたびにそれを再圧縮するのは得策ではありません。 ZIPファイルがまだ存在しない場合にのみ、それを試してください。
-
揮発性ファイル、または圧縮して転送する単一の小さなファイルの場合は、代わりに
ob_start( 'ob_gzhandler')
を使用してみてください。ファイルは圧縮されて転送されますが、クライアント側によって元の形式で保存されます。 -
ダウンローダーがファイルの終わりを認識できるようにContent-Lengthヘッダーを指定する必要があります。これにより、進行状況の制御、ファイルの破損の検出、HTTPセッションのハングの回避が可能になります(ConnectionがKeepの場合-Aliveモード)、このヘッダーの欠如が問題の原因である可能性があります。
他のヒント
この問題が発生し、ダウンロードしたzipファイルの最初に新しい行が挿入されていることが判明しました。
ob_cleanおよびflush関数を使用して解決
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".basename($archive_file_name));
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($archive_file_name));
ob_clean();
flush();
echo readfile("$archive_file_name");
karim79 で示唆されているように、回答としてコメントを付けます。MIMEタイプを変更するとどうなりますかapplication / octet-streamからapplication / zipへ?
また、コマンドラインのzipプログラムを使用しているようですが、zipの成功を確認せず、エンドユーザーのブラウザーに送信する前にファイルが存在するかどうかも確認しません。 zipを使用してファイル名をハードコーディングし、zipファイルが正しく形成されることを保証してから、コードがブラウザに適切に吐き出すかどうかを確認してください。
見ているのは、アーカイブユーティリティがzipファイルをzipファイルとして認識しておらず、zipアーカイブ自体を圧縮しようとしたことです。 2番目の操作は、作成された最初のファイルを解凍するだけなので、実際にファイルを開くことはありません。これは、zipが破損しているためです。
ダウンロードプロセス中に、ブラウザが何らかの方法でzipファイルを破損した可能性があります(改行変換はありますか?)。前述のように、MIMEタイプを確認し、php header()を使用して正しいMIMEタイプ(application / zip)を設定します。