九保すこひ@フリーランスエンジニア|累計300万PVのブログ運営中
さてさて、ウェブサイトの構築をしていると特に管理系のページではファイルをアップロードしたり逆にダウンロードする機能というのが必要になってきたりします。
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
では普通に使ってるのかな??)
ではでは〜!
「今回は文字の量も圧縮バージョンでした😅」