Laravel 5 - Comment accéder à l'image téléchargée dans le stockage dans View?

172

J'ai téléchargé les avatars des utilisateurs dans le stockage Laravel. Comment puis-je y accéder et les rendre dans une vue?

Le serveur pointe toutes les demandes vers /public, alors comment puis-je les montrer si elles se trouvent dans le /storagedossier?

Tadeáš Jílek
la source

Réponses:

349

La meilleure approche est de créer un lien symbolique comme @SlateEntropy très bien indiqué dans la réponse ci-dessous . Pour vous aider, depuis la version 5.3, Laravel inclut une commande qui rend cela incroyablement facile à faire:

php artisan storage:link

Cela crée un lien symbolique de public/storageà storage/app/publicpour vous et c'est tout ce qu'il y a à faire. Désormais, tout fichier dans /storage/app/publicest accessible via un lien comme:

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

Si, pour une raison quelconque, vous ne pouvez pas créer de liens symboliques (peut-être que vous êtes sur un hébergement partagé, etc.) ou si vous souhaitez protéger certains fichiers derrière une logique de contrôle d'accès, il existe une alternative d'avoir une route spéciale qui lit et sert l'image. Par exemple, une route de fermeture simple comme celle-ci:

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;
});

Vous pouvez maintenant accéder à vos fichiers comme vous le feriez si vous aviez un lien symbolique:

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

Si vous utilisez la bibliothèque d'images d'intervention, vous pouvez utiliser sa responseméthode intégrée pour rendre les choses plus succinctes:

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

AVERTISSEMENT

Gardez à l'esprit qu'en servant manuellement les fichiers, vous subissez une pénalité de performances , car vous parcourez tout le cycle de vie de la requête Laravel afin de lire et d'envoyer le contenu du fichier, ce qui est considérablement plus lent que de le faire gérer par le serveur HTTP.

Bogdan
la source
Ça semble bien. Je voudrais poser une autre question. Est-il recommandé de stocker des fichiers tels que des avatars, des pouces, etc. (fichiers téléchargés par les utilisateurs) dans le stockage?
Tadeáš Jílek
5
Vous pouvez les stocker où vous voulez, mais à moins qu'il ne s'agisse de fichiers privés, je pense que vous feriez mieux de les stocker dans le publicrépertoire. De cette façon, vous éviterez de devoir composer une réponse d'image qui pourrait être gérée beaucoup plus rapidement par le serveur HTTP.
Bogdan
2
Personnellement, je ne stockerais pas les fichiers utilisateur dans le dossier public, je trouve les choses beaucoup plus ordonnées et plus gérables lorsque le dossier de stockage est utilisé pour le stockage.
SlateEntropy
2
Je ne recommanderais ni l'un ni l'autre, car vous ajoutez alors la surcharge de chargement de Laravel et / ou de l'utilisation de PHP pour lire chaque image. L'utilisation d'un lien symbolique tel que décrit par CmdSft serait beaucoup plus rapide.
user1960364
4
@ user1960364 C'est pourquoi le dernier paragraphe suggère fortement d'utiliser l'approche du lien symbolique. Mais la réponse elle-même, bien que n'étant pas la meilleure solution du point de vue des performances, est toujours valable et peut être la seule approche pour les personnes exécutant des applications sur des serveurs partagés où les liens symboliques peuvent être impossibles à configurer. La réponse montre également comment vous pouvez servir des fichiers par programme si le besoin s'en fait sentir, peut-être pour servir des fichiers cryptés comme demandé dans cette question .
Bogdan
53

Une option serait de créer un lien symbolique entre un sous-dossier de votre répertoire de stockage et un répertoire public.

Par exemple

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

C'est également la méthode utilisée par Envoyer , un gestionnaire de déploiement construit par Taylor Otwell, le développeur de Laravel.

ArdoiseEntropie
la source
Je suis un peu nouveau dans ce domaine. Cela doit-il être exécuté sur le terminal ou défini dans un fichier de configuration quelque part dans laravel?
Gaurav Mehta
oui, vous devez l'exécuter via la ligne de commande. Il devrait être configuré partout où vous déployez l'application.
SlateEntropy
Pour les utilisateurs de Windows, voici un outil autonome pour cela si vous ne voulez pas utiliser CMD: github.com/amd989/Symlinker#downloads
David
3
La question demandait comment afficher les avatars des utilisateurs stockés storagepubliquement, généralement les avatars ne nécessitent aucun contrôle d'accès. Si aucune sécurité n'est requise, l'utilisation de toute sorte de middleware ou de route est juste un coup perdu pour vos ressources. Il est également intéressant de noter que depuis Laravel 5.2, il existe un fichier séparé "disque" pour les fichiers publics ( laravel.com/docs/5.2/filesystem ) utilisant des liens symboliques.
SlateEntropy
6
Il y a une commande artisan pour faire cela dans Laravel 5.3: $ php artisan storage: link
Phil
22

Selon la documentation de Laravel 5.2, vos fichiers accessibles au public doivent être placés dans le répertoire

storage/app/public

Pour les rendre accessibles depuis le Web, vous devez créer un lien symbolique de public/storageà storage/app/public.

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

Vous pouvez maintenant créer dans votre vue une URL vers les fichiers à l'aide de l'assistant d'actif:

echo asset('storage/file.txt');
Piotr
la source
13

Tout d'abord, vous devez créer un lien symbolique pour le répertoire de stockage à l'aide de la commande artisan

php artisan storage:link

Ensuite, dans n'importe quelle vue, vous pouvez accéder à votre image via un assistant d'URL comme celui-ci.

url('storage/avatars/image.png');
Haider Ali
la source
4

Il est bon de sauvegarder toutes les images et documents privés dans le répertoire de stockage, vous aurez alors un contrôle total sur l'éther de fichier, vous pouvez autoriser certains types d'utilisateurs à accéder au fichier ou à restreindre.

Créez une route / docs et pointez sur n'importe quelle méthode de contrôleur:

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']
    );
}

Lorsque vous frapperez, le localhost:8000/docsfichier sera téléchargé s'il en existe.

Le fichier doit être dans le root/storage/app/users/documentsrépertoire selon le code ci-dessus, cela a été testé sur Laravel 5.4.

Syed Shibli
la source
4

Si vous souhaitez charger un petit nombre d' images privées , vous pouvez encoder les images en base64 et les faire écho <img src="{{$image_data}}">directement dans :

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

J'ai mentionné privé parce que vous ne devriez utiliser ces méthodes que si vous ne voulez pas stocker des images accessibles publiquement via l'URL, à la place, vous devez toujours utiliser la méthode standard (stockage de lien / dossier public et servir des images avec un serveur HTTP).

Méfiez-vous de l' encodage pour base64()avoir deux inconvénients importants:

  1. Cela augmentera la taille de l'image d'environ 30%.
  2. Vous combinez toutes les tailles d'images en une seule requête, au lieu de les charger en parallèle, cela ne devrait pas poser de problème pour certaines petites vignettes, mais pour de nombreuses images, évitez d'utiliser cette méthode.
Arash Moosapour
la source
2

Si vous utilisez php, veuillez simplement utiliser la fonction de lien symbolique php, comme suit:

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

changez le nom d'utilisateur et le nom du projet pour les bons noms.

dagogodboss
la source
1

sans nom de site

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

si vous souhaitez lui ajouter un nom de site, exemple à ajouter sur api JSON felids

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

Si vous êtes comme moi et que vous avez en quelque sorte des chemins de fichiers complets (j'ai fait des correspondances de motifs glob () sur les photos requises, donc je me retrouve à peu près avec des chemins de fichiers complets), et votre configuration de stockage est bien liée (c'est-à-dire telle que vos chemins avoir la chaîne storage/app/public/), alors vous pouvez utiliser mon petit hack sale ci-dessous: 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 '';
    }
Damilola Olowookere
la source
0

Si le disque 'local' ne fonctionne pas pour vous, essayez ceci:

  1. Changer local en public à 'default' => env('FILESYSTEM_DRIVER', 'public'),partir deproject_folder/config/filesystem.php
  2. Effacer le cache de configuration php artisan config:clear
  3. Ensuite, créez un lien sym php artisan storage:link

Pour obtenir l'URL de l'image téléchargée, vous pouvez utiliser ceci Storage::url('iamge_name.jpg');

Dnyaneshwar Harer
la source