Laravel 5-View内のストレージにアップロードされた画像にアクセスする方法


172

Laravelストレージにユーザーのアバターをアップロードしました。それらにアクセスしてビューにレンダリングするにはどうすればよいですか?

サーバーはすべての要求を/publicにポイントしているので、それらが/storageフォルダー内にある場合、どのように表示できますか?

回答:


349

最善のアプローチは、作成することですシンボリックリンク非常によくで指摘@SlateEntropyなどを下記の答え。これを助けるために、バージョン5.3以降、Laravelにこれを信じられないほど簡単にするコマンド含まれています。

php artisan storage:link

これで、からのシンボリックリンクが作成public/storagestorage/app/publicれます。これで、次の/storage/app/publicようなリンクを介してすべてのファイルにアクセスできます。

http://somedomain.com/storage/image.jpg

何らかの理由でシンボリックリンクを作成できない場合(共有ホスティングを使用している場合など)、または一部のアクセス制御ロジックの背後にあるファイルを保護する場合は、読み取りと読み取りを行う特別なルートを使用する方法があります。画像を提供します。たとえば、次のような単純な閉鎖ルート:

Route::get('storage/{filename}', function ($filename)
{
    $path = storage_path('public/' . $filename);

    if (!File::exists($path)) {
        abort(404);
    }

    $file = File::get($path);
    $type = File::mimeType($path);

    $response = Response::make($file, 200);
    $response->header("Content-Type", $type);

    return $response;
});

これで、シンボリックリンクがある場合と同じようにファイルにアクセスできます。

http://somedomain.com/storage/image.jpg

あなたが使用している場合は介入イメージライブラリを、あなたはその中に組み込まれて使用することができますresponse物事をより簡潔にする方法を:

Route::get('storage/{filename}', function ($filename)
{
    return Image::make(storage_path('public/' . $filename))->response();
});

警告

であることに留意してください手動で提供するファイルをあなたが負担しているパフォーマンスの低下をあなたが読んでいるファイルの内容を、送信するために、全体Laravel要求のライフサイクルを通過しているので、かなり遅い HTTPサーバハンドルを持つよりを。


いいですね。もう1つ質問したいと思います。アバターやサムなどのファイル(ユーザーからアップロードされたファイル)をストレージに保存することをお勧めしますか?
TadeášJílek

5
好きな場所に保存できますが、プライベートファイルでない限り、publicディレクトリに保存した方がよいと思います。このようにして、HTTPサーバーでより高速に処理できる画像応答を作成する必要があるというオーバーヘッドを回避します。
ボグダン、

2
個人的には、ユーザーファイルをパブリックフォルダーに保存しません。ストレージフォルダーをストレージに使用すると、より整然として扱いやすくなります。
SlateEntropy

2
Laravelを再度ロードしたり、PHPを利用して各画像を読み取ったりするオーバーヘッドが増えるため、これらのいずれもお勧めしません。CmdSftで記述されているシンボリックリンクを使用すると、はるかに高速になります。
user1960364 2016

4
@ user1960364それが最後の段落がシンボリックリンクアプローチを使うことを強く示唆する理由です。しかし、答え自体は、パフォーマンスの観点からは最善の解決策ではありませんが、依然として有効であり、シンボリックリンクを設定できない共有サーバーでアプリを実行している人にとっては唯一のアプローチである可能性があります。答えは、必要に応じてファイルをプログラムで提供する方法も示しています。おそらく、この質問で尋ねられたような暗号化されたファイルを提供するためです。
ボグダン

53

1つのオプションは、ストレージディレクトリのサブフォルダーとパブリックディレクトリの間にシンボリックリンクを作成することです。

例えば

ln -s /path/to/laravel/storage/avatars /path/to/laravel/public/avatars

これは、Laravelの開発者であるTaylor Otwellによって構築されたデプロイメントマネージャであるEnvoyerでも使用されている方法です。


私はこれが初めてです。これはターミナルで実行する必要があるか、またはlaravelのどこかにある構成ファイルで定義する必要がありますか?
Gaurav Mehta

はい、これをコマンドラインから実行する必要があります。アプリをデプロイする場所であればどこでもセットアップする必要があります。
SlateEntropy 2016年

Windowsユーザーの場合、CMDを使用したくない場合のスタンドアロンツールは次のとおり
David

3
storage一般公開で保存されているユーザーのアバターを表示する方法を尋ねた質問です。通常、アバターはなんらかのアクセス制御を必要としません。何らかのミドルウェアまたはルートを使用してセキュリティが必要ない場合、リソースへの無駄な打撃にすぎません。Laravel 5.2以降では、シンボリックリンクを使用してパブリックファイル(laravel.com/docs/5.2/filesystem)に個別のファイル「ディスク」が存在するため、注目に値します。
SlateEntropy 2016

6
Laravel 5.3でこれを行うには、artisanコマンドがあります:$ php artisan storage:link
Phil

22

Laravel 5.2のドキュメントによると、公開されているファイルはディレクトリに置く必要があります

storage/app/public

Webからアクセスできるようにするには、からpublic/storageへのシンボリックリンクを作成する必要がありますstorage/app/public

ln -s /path/to/laravel/storage/app/public /path/to/laravel/public/storage

これで、アセットヘルパーを使用して、ビューにファイルへのURLを作成できます。

echo asset('storage/file.txt');


13

まず、artisanコマンドを使用して、ストレージディレクトリのシンボリックリンクを作成する必要があります

php artisan storage:link

次に、どのビューでも、このようなURLヘルパーを介して画像にアクセスできます。

url('storage/avatars/image.png');

4

すべてのプライベートイメージとドキュメントをストレージディレクトリに保存すると、特定のタイプのユーザーがファイルにアクセスしたり制限したりできるように、ファイルエーテルを完全に制御できるようになります。

ルート/ドキュメントを作成し、任意のコントローラーメソッドをポイントします。

public function docs() {

    //custom logic

    //check if user is logged in or user have permission to download this file etc

    return response()->download(
        storage_path('app/users/documents/4YPa0bl0L01ey2jO2CTVzlfuBcrNyHE2TV8xakPk.png'), 
        'filename.png',
        ['Content-Type' => 'image/png']
    );
}

あなたがヒットするとき、localhost:8000/docsファイルが存在する場合はダウンロードされます。

ファイルはroot/storage/app/users/documents上記のコードに従ってディレクトリにある必要がありますLaravel 5.4。これはでテストされました。


4

少数のプライベートイメージをロードする場合は、イメージをbase64にエンコードして、<img src="{{$image_data}}">直接エコーすることができます。

$path = image.png
$full_path = Storage::path($path);
$base64 = base64_encode(Storage::get($path));
$image_data = 'data:'.mime_content_type($full_path) . ';base64,' . $base64;

これらのメソッドを使用するのは、urlを介してパブリックにアクセスできるようにしたくない場合にのみ使用する必要があるためです。代わりに、常に標準の方法を使用する必要があります(リンクストレージ/パブリックフォルダーを使用して、HTTPサーバーでイメージを提供する)。

エンコーディングにbase64()は2つの重要な欠点があることに注意してください

  1. これにより、画像サイズが約30%増加します。
  2. すべての画像サイズを1つの要求で組み合わせて、それらを並行してロードするのではなく、これは一部の小さなサムネイルでは問題になりませんが、多くの画像ではこの方法の使用を避けます。

2

phpを使用している場合は、次のようにphp symlink関数を使用してください。

symlink('/home/username/projectname/storage/app/public', '/home/username/public_html/storage')

ユーザー名とプロジェクト名を正しい名前に変更します。


1

サイト名なし

{{Storage::url($photoLink)}}

サイト名を追加してAPI JSON felidsに追加する例

 public function getPhotoFullLinkAttribute()
{
    return env('APP_URL', false).Storage::url($this->attributes['avatar']) ;
}

0

あなたが私のようなもので、どういうわけか完全なファイルパスがあり(必要な写真でglob()パターンマッチングを行ったので、ファイルの完全なパスがほとんどになる)、ストレージ設定は適切にリンクされている(つまり、パスが文字列storage/app/public/)があれば、以下の小さな汚いハックを使用できます:p)

 public static function hackoutFileFromStorageFolder($fullfilePath) {
        if (strpos($fullfilePath, 'storage/app/public/')) {
           $fileParts = explode('storage/app/public/', $fullfilePath);
           if( count($fileParts) > 1){
               return $fileParts[1];
           }
        }

        return '';
    }

0

ディスク「ローカル」が機能していない場合は、これを試してください:

  1. 公衆への局所的な変化'default' => env('FILESYSTEM_DRIVER', 'public'),からproject_folder/config/filesystem.php
  2. 構成キャッシュをクリア php artisan config:clear
  3. 次に、シンボリックリンクを作成します php artisan storage:link

アップロードされた画像のURLを取得するには、これを使用できます Storage::url('iamge_name.jpg');

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.