はじめに
この記事はLaravelアプリケーションの実装において、
Amazon S3(以下、S3と記載)にファイルがアップロードされているかをチェックしようとして、
3時間近く沼ってしまった今日の自分に捧げます。
環境
Laravel: 8
PHP: 7.4
PC: MacOS14(Sonoma)
結論
S3のバケットポリシーによって、S3にアップロードされているファイルへのアクセス権限がない状態だと、
LaravelのStorageクラスを使用してもファイルの存在が確認できなくなる。
// ファイルへのアクセス権限がないと、結果は必ずfalse(ファイルが存在していない)になる
Storage::exists('S3上のファイルパス');
バケットポリシー以外のアクセス権限でも、同様の影響を及ぼすかは不明。
経緯
S3で同じ名前のファイルが既に存在するかどうかの確認が必要だったため、以下のコードを実装しました。
if (Storage::exists('ファイルパス')) {
// 同じ名前のファイルがS3上にあった場合の処理
return;
}
// 同じ名前のファイルがS3上にない場合の処理
実装はサクッと終わり、いざ動作確認を開始するも、
if文の中の処理が実行されない現象に直面しました。
最初は、existsメソッドに渡していた引数の問題ではないかと考え、
階層ごとにexistsメソッドの動きをチェックしてみると、このような結果になりました。
Storage::exists('最上位ディレクトリパス'); // true、期待通り
Storage::exists('最上位ディレクトリパス/次の階層ディレクトリパス'); // true、期待通り
Storage::exists('最上位ディレクトリパス/次の階層ディレクトリパス/確認したいファイル'); // false、期待外れ...
ディレクトリの存在確認は期待通りに機能していましたが、ファイル自体の存在確認になると、
ファイルが存在していないとなってしまう...なぜだ。
この段階で一旦仮説を立てました。
S3バケットに設定されている、ファイルへのアクセス権限が影響しているのではないかと。
というのも今、ファイルの存在確認をしているS3バケットには、
S3バケットポリシーによってIPアドレス制限がかけられていたため、自宅で作業していた私はファイルへアクセスする権限がなかったのです。
ということでS3バケットへアクセスできる、
会社に出社しているメンバーに動作を確認してもらうと...
Storage::exists('最上位ディレクトリパス/次の階層ディレクトリパス/確認したいファイル'); // true、期待通り!
はい、期待どおり動きました!!!
ファイルへのアクセス権限がない場合、まさかファイルのダウンロードだけではなく、
ファイルの存在確認まで制限されているとは思ってもいませんでした...
こちらのS3のドキュメントにも、
この点については明記されていなかったため、完全に見落としていました...
まあ、ダウンロードができないなら、ファイルの存在確認もさせないのは理にかなっているのか...
終わりに
今日の自分へ。
S3バケットポリシーでアクセス制限をされている場合には、
ファイルのダウンロードだけではなくファイルが存在しているかの確認もできないぞ!
S3バケットポリシー以外のアクセス制限でも、
同じようにファイルの存在が確認できないようになるのか、
知っている方がいると教えていただけると幸いです。