web-dev-qa-db-ja.com

PHPオンザフライでファイルを圧縮する

サーバー上のフォルダーから2つのファイルを圧縮して強制的にダウンロードする最も簡単な方法は何ですか? 「Zip」をサーバーに保存せずに。

    $Zip = new ZipArchive();
   //the string "file1" is the name we're assigning the file in the archive
$Zip->addFile(file_get_contents($filepath1), 'file1'); //file 1 that you want compressed
$Zip->addFile(file_get_contents($filepath2), 'file2'); //file 2 that you want compressed
$Zip->addFile(file_get_contents($filepath3), 'file3'); //file 3 that you want compressed
echo $Zip->file(); //this sends the compressed archive to the output buffer instead of writing it to a file.

誰か確認できますか:test1.doc、test2.doc、およびtest3.docのフォルダーがあります

上記の例では-file1(file2およびfile3)は単にtest1.docなどです。

「$ filepath1」で何かする必要がありますか?それは3つのドキュメントを保持するフォルダディレクトリですか?

基本的な質問で申し訳ありません。

45
Steven

残念ながらw/PHP 5.3.4-devおよびCentOS 5.xのZend Engine v2.3.0上記のコードを動作させることができませんでした。 "無効またはユニット化されたZip object "エラーメッセージだけで取得できました。そのため、次のスニペットを使用する必要がありました(PHP.netマニュアルのZipArchive :: openページのJonathan Baltazarの例から引用)。 :

// Prepare File
$file = tempnam("tmp", "Zip");
$Zip = new ZipArchive();
$Zip->open($file, ZipArchive::OVERWRITE);

// Stuff with content
$Zip->addFromString('file_name_within_archive.ext', $your_string_data);
$Zip->addFile('file_on_server.ext', 'second_file_name_within_archive.ext');

// Close and send to users
$Zip->close();
header('Content-Type: application/Zip');
header('Content-Length: ' . filesize($file));
header('Content-Disposition: attachment; filename="file.Zip"');
readfile($file);
unlink($file); 

私はこれがメモリのみの作業とは異なることを知っています-あなたのRAMにtmp領域がある場合を除きます;-)-しかし、これは私と同じように上記の解決策に苦労している誰かを助けることができます;パフォーマンスの低下は問題ではありません。

69
maraspin

Zipコマンドラインユーティリティにアクセスできる場合は、試すことができます

<?php
$zipped_data = `Zip -q - files`;
header('Content-type: application/Zip');
header('Content-Disposition: attachment; filename="download.Zip"');
echo $zipped_data;
?>

ここで、filesは圧縮したいもので、Zip実行可能ファイルに場所を圧縮します。

もちろん、これはLinuxまたは同様のものを想定しています。 Windowsでは、他の圧縮ツールでも同様のことができると思います。

Zip extension 、使用方法 here もあります。

5
Vinko Vrsalovic

maraspin's Answerは私が試したものです。奇妙なことに、ファイルサイズを参照するヘッダー行を削除することで機能しました。

header('Content-Length: ' . filesize($file));

上記の変更により、コードは簡単に動作します!この変更なしでは、次のエラーメッセージが表示されていました。

中央ディレクトリの終わりの署名が見つかりません。このファイルはzipファイルではないか、マルチパートアーカイブの1つのディスクを構成しています。後者の場合、中央ディレクトリとzipファイルのコメントは、このアーカイブの最後のディスクにあります。

テスト環境:

OS:Ubuntu 10.10ブラウザ:FirefoxそしてデフォルトのLAMPスタック。

4
itsols

itsols 'Content-Length'を挿入する場合は、次のようにします。

$length = filesize($file);
header('Content-Length: ' . $length);

理由はわかりませんが、同じ行に配置するとクラッシュします。

1
Arkiller

オンザフライ(メモリ内)でZipファイルを作成するには、 phpMyAdminZipFileクラスを使用できます。

独自のアプリケーションで使用する方法の例:

注:ZipファイルはPHPのメモリ制限によって制限され、制限を超えるとアーカイブが破損します。

1
dezlov