九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、ウェブサイトの構築をしていると特に管理系のページではファイルをアップロードしたり逆にダウンロードする機能というのが必要になってきたりします。
Laravelを使えばアップロード&ダウンロード機能はそれほど難しいわけでもありませんが、それでもダウンロードするファイルを圧縮、または複数のファイルを1つに固めてダウンロードするとなったらどうでしょう。さすがにそこまではLaravelといえども面倒は見てくれないので、これは自分自身で実装する必要があります。
そこで!
今回は、そんな圧縮や展開(昔で言う解凍)する機能をLaravelで実装する方法をお届けします。
ぜひ皆さんのお役に立てると嬉しいです!

開発環境: Laravel 5.8
目次
前提として
gzipとbz2は、それぞれ以下のPHPモジュールが有効になっている必要があります。
- gzip ・・・ zlib
- bz2 ・・・ bz2
phpinfo()で表示した内容が以下のようになっていれば有効になっています。


私の環境ではすでにインストールされた状態でしたが、もしインストールされていない場合は以下のようにしてコマンドからパッケージを検索してみるといいでしょう。
sudo apt search php | grep bz2
ファイルを圧縮してダウンロードする
zip圧縮してダウンロードする
zipでひとつのファイルにまとめるにはZipArchiveを使います。
$save_path = storage_path('app/test.zip');
$zip = new \ZipArchive();
$zip->open($save_path, \ZipArchive::CREATE);
for($i = 1 ; $i <= 3 ; $i++) {
$filename = 'test_'. $i .'.txt'; // test_1.txt 〜 test_3.txt
$file_path = storage_path('app/'. $filename);
// ファイルを追加
$zip->addFile($file_path, $filename);
// 文字列から追加
$zip->addFromString('additional.txt', '文字列からファイル追加');
}
$zip->close();
return response()->download($save_path);
まず$save_pathですが、これは今からつくるzipファイルの保存場所になります。
そして、ループの中でzipファイルの中身を追加しています。
- addFile ・・・ ファイルを追加
- addFromString ・・・ 文字列からファイルを追加
ここで重要なのがaddFile()の第2引数、addFromString()の第一引数の「ローカル名」です。
これは、展開(解凍)した際のパスにあたるもので、例えば、以下のようにするとtextsの中に各ファイルを格納することができます。
$zip->addFile($file_path, 'texts/'. $filename);
実際にtextsをつけてzip化させた場合のファイル構成はこちら。

gzip圧縮してダウンロードする
gzip圧縮の場合は、PharDataを使います。
$tar_path = storage_path('app/test.tar');
$gzip_path = storage_path('app/test.tar.gz');
$pd = new \PharData($tar_path);
for($i = 1 ; $i <= 3 ; $i++) {
$filename = 'test_'. $i .'.txt'; // test_1.txt 〜 test_3.txt
$file_path = storage_path('app/'. $filename);
// ファイルを追加
$pd->addFile($file_path, $filename);
// 文字列から追加
$pd->addFromString('additional.txt', '文字列からファイル追加');
}
$pd->compress(\Phar::GZ);
// @unlink($tar_path);
return response()->download($gzip_path);
基本的には、zip圧縮のZipArchiveと同じですが、ひとつ違うのはgzipファイルを作成する手順が以下のようになる部分です。
- tarファイルをつくる
- tar.gz(gzip)ファイルをつくる
つまり、結果的にtarファイルとtar.gzファイル2つが作成されるので、不要であれば自分で削除する必要があるということです。コメント化していますがコードの最後の方でunlink()を使っているのはこのためです。
bz2圧縮してダウンロードする
bz2圧縮はgzip圧縮とほぼ同じです。
$tar_path = storage_path('app/test.tar');
$bz2_path = storage_path('app/test.tar.bz2');
$pd = new \PharData($tar_path);
for($i = 1 ; $i <= 3 ; $i++) {
$filename = 'test_'. $i .'.txt'; // test_1.txt 〜 test_3.txt
$file_path = storage_path('app/'. $filename);
// ファイルを追加
$pd->addFile($file_path, $filename);
// 文字列から追加
$pd->addFromString('additional.txt', '文字列からファイル追加');
}
$pd->compress(\Phar::BZ2);
// @unlink($tar_path);
return response()->download($bz2_path);
gzipと違っているのは、保存するパスと以下の圧縮パラメータです。
$pd->compress(\Phar::BZ2);
ちなみに
エラーが発生したら
以下のようなエラーが発生した場合は、「すでに同じ名前のファイルがあるので先に消してね」という意味ですので、先にファイルをunlink()などで削除してから圧縮を実行してください。
phar "******" exists and must be unlinked prior to conversion
ダウンロードしたら元ファイルを削除した場合
開発内容によっては、ダウンロードしたファイルをわざわざサーバーに置いておかなくてもいい場合があると思います。そんな場合以下のようにdeleteFileAfterSend()をつけるだけで自動的に削除してくれます。
return response()->download($save_path)->deleteFileAfterSend();
ダウンロードするファイルの名前を指定する
Laravelのダウンロードでファイル名を指定をするにはdownload()の第2引数に名前を入れるだけでOKです。
return response()->download($bz2_path, 'my.tar.gz');
おわりに
ということで、今回はLaravelで圧縮ファイルを作成してダウンロードする方法をご紹介しました。
ダウンロード部分はLaravelのみしか有効ではありませんが、圧縮部分はPHP単体でも、その他のフレームワークでも使えると思いますので、ぜひ参考になると嬉しいです。
ちなみにその昔よくlzh形式とかrar形式のファイルとかってあったと思いますが、最近見なくなってしまいました。(windowsでは普通に使ってるのかな??)
ではでは〜!
「今回は文字の量も圧縮バージョンでした😅」





