実現したいこと
S3にある画像をまとめてダウンロードする。JavaScriptで無理やりやる方法もあるが、
ブラウザ側でアラートが発生するため、zipダウンロードを選択しました。
環境
- macOS Mojave 10.14.6
- Laravel6系
- PHP7.2
流れ
- S3を利用する設定をする。
- S3->サーバーに画像をダウンロード
- ZipArchiveを利用して画像をzipファイルにまとめる
- ダウンロードレスポンスとして、ブラウザに返す。
※当初、ZipArchiveよりも少し簡単に利用できそうな、
Zipperというパッケージの利用を考えていましたが、Laravel6系に対応していませんでした。
実装
※現時点では、自身のMacbook上でのみ動作を確認していおります。
S3を利用する設定をする。
envファイルに設定情報を記述します。
.env
AWS_ACCESS_KEY_ID=***
AWS_SECRET_ACCESS_KEY=***
AWS_DEFAULT_REGION=***
AWS_BUCKET=***
以下3つを一気に実装
- S3->サーバーに画像をダウンロード
- ZipArchiveを利用して画像をzipファイルにまとめる
- ダウンロードレスポンスとして、ブラウザに返す。
一気に処理を書いていきます。適宜、メソッドや別クラスに処理を分けてください。
TestController.php
use ZipArchive;
use Aws\CommandPool;
use Aws\S3\S3Client;
(中略)
public function zipDownLoad(ZipArchive $zip)
{
// バケット
$bucket = config('filesystems.disks.s3.bucket');
$imgDir = 'imgs';
// 画像ファイル名
$imgs = [
'img1.jpg',
'img2.jpg',
'img3.jpg',
'img4.jpg',
'img5.jpg',
];
// S3Client ※1
$s3Client = new S3Client(
[
'version' => 'latest',
'region' => config('filesystems.disks.s3.region');,
'credentials' => [
'secret' => config('filesystems.disks.s3.secret');,
'key' => config('filesystems.disks.s3.key');,
],
]
);
// zipファイル名と保存先(あとで削除する)
$zipFileName = 'test.zip';
$zipFilePath = public_path() . '/' . $zipFileName;
// レスポンスヘッダー
$headers = ['Content-Type' => 'application/zip'];
// 画像取得 ※2
$commands = [];
foreach ($imgs as $img) {
$key = $imgDir . $img;
$commands[] = $s3Client->getCommand(
'GetObject',
[
'Bucket' => $bucket,
'Key' => $key,
]
);
}
$contents = CommandPool::batch($s3Client, $commands);
// zipファイル作成 ※3
$zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE);
foreach ($contents as $i => $content) {
// 取得できなかったらS3Exceptionが格納されてる。
if (strpos(get_class($content), 'S3Exception') !== false) {
continue;
}
$zip->addFromString($imgs[$i], $content['Body']);
}
$zip->close();
// おまじない ※4
ob_end_clean();
// 返却
return response()
->download($zipFilePath, $zipFileName, $headers) // ※5
->deleteFileAfterSend(true); // ※6
}
- ※2のCommandPoolを使うため、Storageファサードではなく、S3Clientを生成しています。
- S3に対してまとめてコマンド実行しています。参考
- ZipArchive::CREATEは「新規作成」、ZipArchive::OVERWRITEは「存在していたら上書き」という意味
- この関数を実行しないとMacでは正しく解凍できない。参考
- 引数は(ファイルパス, ダウンロードされるサイトのファイル名, レスポンスヘッダー)。第2,3引数は任意
- レスポンス返却後にファイルを削除