🪣
【Laravel 9~】StorageクラスでS3内のバケット間でファイルコピーする
結論
config/filesystems.php
の設定が以下の通りだとして...
<?php
return [
...
'disks' => [
...
// コピー元のS3バケット
's3_from' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID') ?: null,
'secret' => env('AWS_SECRET_ACCESS_KEY') ?: null,
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET_FROM'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_URL'),
],
// コピー先のS3バケット
's3_to' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID') ?: null,
'secret' => env('AWS_SECRET_ACCESS_KEY') ?: null,
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET_TO'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_URL'),
],
],
];
以下のようにすればOK
use Illuminate\Filesystem\AwsS3V3Adapter;
/** @var AwsS3V3Adapter $fromStoragen */
$fromStorage = Storage::drive('s3_from');
/** @var AwsS3V3Adapter $toStorage */
$toStorage = Storage::drive('s3_to');
// 異なるバケット間でファイルコピーを実行
$fromStorage->getClient()->copy(
$fromStorage->getConfig()['bucket'], // コピー元バケット名
'path/to/original_file.png', // コピー元バケット内のファイルパス
$toStorage->getConfig()['bucket'], // コピー先バケット名
'path/to/copied_file.png', // コピー先バケット内のファイルパス
'public-read', // visibility設定(非公開なら'private'指定)
);
余談
S3Client
を直接操作したい
S3Clientを直接操作したい場合、以下のようにgetClient
関数で取り出せる
use Aws\S3\S3Client;
/** @var S3Client $s3Client */
$s3Client = Storage::drive('s3_from')->getClient();
config/filesystems.php
の設定値はgetConfig()
で取得できるので、あとは好き放題!
$diskConfig = Storage::drive('s3_from')->getConfig();
[
'driver' => 's3',
'key' => '...',
'secret' => '...',
'region' => 'ap-northeast-1',
'bucket' => 'bukcet-name-from',
'url' => 'https://...',
'endpoint' => 'https://...',
];
Storageクラスの思想について
- Laravelの思想的にStorageクラスの抽象化が進んでいる
- ...ので、S3Clientを取り出して実装するのは本来的にあんまり良くない気がする
- とはいえ必要に応じて直接S3Clientを使いたいケースはあるよね...という話
同一バケット内のコピーであれば、よりシンプルに実装可能
Storage::drive('s3_foo')->copy('old/file.jpg', 'new/file.jpg');
Discussion