Laravel 6.x bladeのaタグでS3からファイルダウンロード

### index.blade.php
aタグでは、actionでコントローラへリンクします。その際に、S3のファイルを指定するための引数を渡します。

<a href="{{ action('HogesController@download', $data->id) }}">{{ substr($data->attachment_file }}</a>

### route
ルーティングはgetメソッドで大丈夫です。

Route::get('/download/{id}', 'HogesController@download');

### controller
1. 渡ってきた引数($id)を元に、DB保存してあったS3のファイル名(ファイルパス)を取得します。
2. ファイルのmimeTypeを取得し、ContentTypeに指定します。
3. headerを指定してreturnで返します。

public function download($id){
        $data = Data::where('id', $id)->first();
        $file_path = '/hogehoge/prd/'.$data->attachment_file; 

        $mimeType = Storage::disk('s3')->mimeType($file_path);
        $file_name = $data->attachment_file;

        $headers = [
            'Content-Type' => $mimeType,
            'Content-Disposition' => 'attachment; filename="'. $file_name. '"'
        ];
        return \Response::make(Storage::disk('s3')->get($file_path), 200, $headers);
    }

てっきりDownloadの処理はview側で書くのかと思いましたが、コントローラーに引数を渡してコントローラーで処理する方が一般的のようです。
しかし、S3のディレクトリ構造をどのようにして、ディレクトリ名・ファイル名のどこまでをDBに保存するか悩みます🤔🤔🤔

Laravel 6.xでS3への保存・呼び出し方法

– hasManyの1M以下のファイルを、storage保存から、S3保存に切り替えたい
### 現状:storage保存

if($file = $request->file('file')){
            $path = $file->getClientOriginalName();
            $file->storeAs('./public/files/tmp/', $path);
            $inputs['path'] = $path;
        } else {
            $inputs['path'] = '';
        }

## 手順
### 1. AWSマネージメントコンソールログイン
https://ap-northeast-1.console.aws.amazon.com/
ユーザ名メニュー 「My Security Credentials」 -> IAMページ表示

### 2. S3用のIAM作成
Users -> Add user
1ページ目
– User name: [ ${project name} ]
– Select AWS access type: check [Programmatic access] ※Enables an access key ID and secret access key for the AWS API, CLI, SDK, and other development tools.

2ページ目
– Set permissions: [Attach existing policies directly]
— [AmazonS3FullAccess]

3ページ目
– Add tags (optional): none

4ページ目
– Review: nothing to do

5ページ目
– User name: ${project name}
– Access key ID : 新規発行
– Secret access key : 新規発行

### 3. S3 bucket作成
https://s3.console.aws.amazon.com/s3/home?region=ap-northeast-1
1ページ目
– Bucket name: [ ${project name} ]
– Region: [Asia Pacific (Tokyo)]

2ページ目
– Properties : 必要に応じて設定

3ページ目
– Block public access : off

4ページ目
– review -> create bucket

### 4. composerインストール
https://readouble.com/laravel/6.x/ja/filesystem.html#driver-prerequisites

// out of memoryとなるのでswapメモリを追加
$ sudo /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
$ sudo /sbin/mkswap /var/swap.1
$ sudo /sbin/swapon /var/swap.1
$ free

// s3パッケージインストール
$ php composer.phar require league/flysystem-aws-s3-v3 ~1.0
// キャッシュアダプタインストール(公式ドキュメントに絶対に必要と書いてある。。)
$ php composer.phar require league/flysystem-cached-adapter ~1.0

### 5. envファイルにS3アクセス情報追記

AWS_ACCESS_KEY_ID=${access_key}
AWS_SECRET_ACCESS_KEY=${secrete_access_key}
AWS_DEFAULT_REGION=ap-northeast-1
AWS_BUCKET=${bucket name}

### 6. controllerから保存
putFileAs(‘S3ディレクトリ’, $file, ‘filename’, ‘public’) で保存。
ファイル名を気にしない場合はputFileでもOK

if($file = $request->file('file')){
            $path = $file->getClientOriginalName();
            Storage::disk('s3')->putFileAs('/', $file, $path,'public');
            $inputs['path'] = $path;
        } else {
            $inputs['path'] = '';
        }

### 7. S3ファイルの表示

Route::get('/read', function(){
	$path = Storage::disk('s3')->url('image.jpeg');
	return "<img src=".$path.">";
});

思ったより簡単でワロタ。ベタがきだと、もう少しコードが必要だった記憶があります。