質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

nginx

nginixは軽量で高性能なwebサーバーの1つです。BSD-likeライセンスのもとリリースされており、あわせてHTTPサーバ、リバースプロキシ、メールプロキシの機能も備えています。MacOSX、Windows、Linux、上で動作します。

Amazon S3

Amazon S3 (Simple Storage Service)とはアマゾン・ウェブ・サービスが提供するオンラインストレージサービスです。

Q&A

解決済

2回答

3313閲覧

S3上のファイルをダウンロードすると画像のみ404になる(Laravel )

uchida_yuma

総合スコア44

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

nginx

nginixは軽量で高性能なwebサーバーの1つです。BSD-likeライセンスのもとリリースされており、あわせてHTTPサーバ、リバースプロキシ、メールプロキシの機能も備えています。MacOSX、Windows、Linux、上で動作します。

Amazon S3

Amazon S3 (Simple Storage Service)とはアマゾン・ウェブ・サービスが提供するオンラインストレージサービスです。

0グッド

0クリップ

投稿2020/05/30 01:20

前提・実現したいこと

お世話になっております。

Laravelを通じてS3バケットからファイルをダウンロードする機能を作りましたが、本番環境のみで動かない状態です。
画像のみ404になってしまい、ハマっているので、何かお気づきの点があれば教えていただけますと幸いです。

現在の状況

/fileDownload/24238/CnqOBtS3GpetBXmtoy9u.jpg?name=jpgtest.jpg

このようなルーティングでS3にあるファイル名とダウンロード名(リアルファイル名)をダウンロードしたいのですが、本番環境の画像のみ404になってしまいます。

コントローラーは以下のようになります。

php

1 public function downloadFile($id, $file, Request $request) 2 { 3 $originalName = $request->get('name'); 4 $content = Storage::disk('s3')->get("documents/$id/$file"); 5 6 $explode = explode('.', $file); 7 $contentType = last($explode); 8 9 $headers = [ 10 'Content-Type' => $contentType, 11 'Content-Description' => 'File Transfer', 12 'Content-Disposition' => "attachment; filename={$originalName}", 13 'filename' => $originalName, 14 ]; 15 16 return response($content, 200, $headers); 17 }

以下のような画像以外の拡張子は正常にダウンロードされます。
/contact/fileDownload/24238/drrnyNrAUheXcxEbTDoJ.csv?name=user.csv

本番環境とローカル環境の違いはサーバーで、

ローカル環境: php7.3-apacheのdocker-image
本番環境: AWS Lightsail php7.3 + nginx1.10

なので、nginxあたりが問題なのかなと考えています。

発生している問題・エラーメッセージ

画像のみ404エラー
イメージ説明

該当のソースコード

ルーティング

php

1 Route::get('fileDownload/{id}/{file}', 'ContactController@downloadFile')->name('download.file');

View

php

1 <a class="btn btn-primary" href="{{ route('download.file', ['id' => $contact->id,'file' => $contact->document3, 'name' => $contact->document3_original_name ]) }}">ダウンロード</a>

試したこと

URLパラメーター化

クエリパラメーターではなく、URLパラメーターに設定しましたが、同じ症状でした。

ルーティング

php

1 Route::get('fileDownload/{id}/{file}/{originalName}', 'ContactController@downloadFile')->name('download.file');

コントローラー

php

1 public function downloadFile($id, $file, $originalName) 2 { 3 $content = Storage::disk('s3')->get("documents/$id/$file"); 4 5 $explode = explode('.', $file); 6 $contentType = last($explode); 7 8 $headers = [ 9 'Content-Type' => $contentType, 10 'Content-Description' => 'File Transfer', 11 'Content-Disposition' => "attachment; filename={$originalName}", 12 'filename' => $originalName, 13 ]; 14 15 return response($content, 200, $headers); 16 }

View

php

1 <a class="btn btn-primary" href="{{ route('download.file', ['id' => $contact->id,'file' => $contact->document3, 'name' => $contact->document3_original_name ]) }}">ダウンロード</a>

nginx設定の確認

conf

1http { 2 3 ## 4 # Basic Settings 5 ## 6 7 sendfile on; 8 tcp_nopush on; 9 tcp_nodelay on; 10 keepalive_timeout 65; 11 types_hash_max_size 2048; 12 # server_tokens off; 13 14 # server_names_hash_bucket_size 64; 15 # server_name_in_redirect off; 16 17 include /etc/nginx/mime.types; 18 default_type application/octet-stream;

mimetypesにも記述してあり問題ありませんでした。

URLから拡張子を削除

以下のようにURLから拡張子を除くとダウンロードが成功します。
イメージ説明

補足情報(FW/ツールのバージョンなど)

php: 7.39
nginx: 1.10
larval 6.0

以上になります。どうぞよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ぱっと見、Laravel ではなく Nginx が 404 ページを返しているように見えます。
Content-Type は拡張子とは違うもので、image/png のような形式になるんですけど、そこを直してみたらどうなりますか?

簡単な実装例 :

php

1$contentTypes = [ 2 'jpg' => 'image/jpeg', 3 'jpeg' => 'image/jpeg', 4 'png' => 'image/png', 5]; 6 7$explode = explode('.', $file); 8$extension = last($explode); 9$contentType = $contentTypes[$extension] ?? 'application/octet-stream';

投稿2020/06/01 07:37

yuuAn

総合スコア44

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uchida_yuma

2020/06/01 21:57

ご回答ありがとうございました。 yuuAnさんのNginxが404を返しているとのご回答からヒントを得て自己解決いたしました。
guest

0

自己解決

URLの最後に拡張子が入っていることにより、リアルなファイルを探しに行っていたようで、以下のように変更すると、無事に画像ダウンロードができました

ルーティング

php

1Route::get('fileDownload/{id}', 'ContactController@downloadFile')->name('download.file')

コントローラー

php

1 public function downloadFile($id, Request $request) 2 { 3 $file = $request->get('file'); 4 $originalName = $request->get('originalName'); 5 $content = Storage::disk('s3')->get("documents/$id/$file"); 6 7 $explode = explode('.', $file); 8 $contentType = last($explode); 9 10 $headers = [ 11 'Content-Type' => $contentType, 12 'Content-Description' => 'File Transfer', 13 'Content-Disposition' => "attachment; filename={$originalName}", 14 'filename' => $originalName, 15 ]; 16 17 return response($content, 200, $headers); 18 } 19

投稿2020/06/01 22:00

uchida_yuma

総合スコア44

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問