ハマる人はハマるかもしれないのでメモ。
事象
LaravelからS3にファイルアップロード後、保存したファイルのURLが正常に取得できない事象が発生。
通常、LaravelからS3にファイルをUPする際は、以下のような形式で行うが、
//ファイルアップロード(putメソッドでアップロード実行し、返り値にS3アップ後のファイル名が取得できる)
$s3_file_name = Storage::disk('s3')->put('/', $file, 'public');
//ファイルURL取得(urlメソッドの引数にS3でのファイル名を指定)
$url = Storage::disk('s3')->url($s3_file_name);
今回はアップロード先をルートではなく配下のuserディレクトリにしたかったので、こう書いた。
// putメソッドの第一引数を'/user/'に指定
$file_name = Storage::disk('s3')->put('/user/', $file, 'public');
その結果、無事にアップロードはできたが、なぜかurlメソッドで取得するファイルのURLに不具合が起きてしまった。
原因
putメソッドの引数の最後に"/"は不要だった。
"/"をつけると、返却されるファイル名の先頭に"/"がついてしまう事象が起きる。
//正常例
$s3_file_name == "9WJnNeebi.jpg"
//おかしい例
$s3_file_name == "/9WJnNeebi.jpg"
この存在しない"/9WJnNeebi.jpg"というファイル名を引数としてurlメソッドに渡していたため、urlメソッドの挙動もおかしくなってしまっていた。
対処方法
putメソッドの引数を'/user'に修正しました。
// putメソッドの第一引数を'/user'に指定
$file_name = Storage::disk('s3')->put('/user', $file, 'public');
これにより正確なファイル名が取得でき、同時に正確なURLも取得できた。
補足
ファイルのURLを取得するurlメソッドの挙動が変だった。
正常なURL => "https://sample-bucket.s3-ap-northeast-1.amazonaws.com/user/DMQKRLJTuDenPXMLB7i0CCkbaHtWjgNN6D6ZPYDA.jpg"
引数ミスった時の返却値 => "https://sample-bucket.s3.ap-northeast-1.amazonaws.com/user//DMQKRLJTuDenPXMLB7i0CCkbaHtWjgNN6D6ZPYDA.jpg"
putメソッドの挙動から、最後のファイル名の先頭に"/"がつくのは当然として、
ドメイン名が「s3-ap-northeast-1」から「s3.ap-northeast-1」に書き換わってしまっている。どうやら引数に「S3内に存在しないファイル名」を渡すと発生する模様。
試しにドメイン名を同じように書き換えてアクセスしてみたらなんと普通にアクセスできてしまった。なんでやねん。