Laravel 5 - Come accedere all'immagine caricata in archivio in Visualizza?


172

Ho gli avatar dell'utente caricati nello spazio di archiviazione di Laravel. Come posso accedervi e renderli in una vista?

Il server punta a tutte le richieste /public, quindi come posso mostrarle se si trovano nella /storagecartella?

Risposte:


349

L' approccio migliore è quello di creare un collegamento simbolico come @SlateEntropy ben indicato nella risposta di seguito . Per aiutarlo, dalla versione 5.3, Laravel include un comando che lo rende incredibilmente facile da eseguire:

php artisan storage:link

Questo crea un collegamento simbolico da public/storagea storage/app/publicper te e questo è tutto ciò che c'è da fare. Ora è /storage/app/publicpossibile accedere a qualsiasi file in tramite un collegamento come:

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

Se, per qualsiasi motivo, non riesci a creare collegamenti simbolici (forse sei su hosting condiviso, ecc.) O vuoi proteggere alcuni file dietro una logica di controllo dell'accesso, c'è l'alternativa di avere un percorso speciale che legge e serve l'immagine. Ad esempio una semplice via di chiusura come questa:

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

Ora puoi accedere ai tuoi file come faresti se avessi un link simbolico:

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

Se stai utilizzando la libreria di immagini di intervento , puoi utilizzare il suo responsemetodo integrato per rendere le cose più sintetiche:

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

AVVERTIMENTO

Tieni presente che servendo manualmente i file stai subendo una penalità per le prestazioni , perché stai attraversando l'intero ciclo di vita della richiesta Laravel per leggere e inviare il contenuto del file, che è notevolmente più lento rispetto alla gestione da parte del server HTTP.


Questo sembra buono. Vorrei fare un'altra domanda. Si consiglia di archiviare file come avatar, pollici e così via (file caricati dagli utenti) nella memoria?
Tadeáš Jílek,

5
Puoi memorizzarli dove vuoi, ma a meno che non si tratti di file privati, penso che sia meglio archiviarli nella publicdirectory. In questo modo eviterai il sovraccarico di dover comporre una risposta di immagine che potrebbe essere gestita molto più velocemente dal server HTTP.
Bogdan,

2
Personalmente non archiverei i file utente nella cartella pubblica, trovo le cose molto più ordinate e più gestibili quando la cartella di archiviazione viene utilizzata per l'archiviazione.
SlateEntropy,

2
Non consiglierei nessuno dei due perché poi stai aggiungendo il sovraccarico di caricare nuovamente Laravel e / o sfruttare PHP per leggere ogni immagine. L'uso di un collegamento simbolico come descritto da CmdSft sarebbe molto più veloce.
user1960364,

4
@ user1960364 Ecco perché l'ultimo paragrafo suggerisce fortemente di utilizzare l'approccio symlink. Ma la risposta stessa, sebbene non sia la migliore soluzione dal punto di vista delle prestazioni, è ancora valida e potrebbe essere l'unico approccio per le persone che eseguono app su server condivisi in cui i collegamenti simbolici potrebbero essere impossibili da configurare. La risposta mostra anche come è possibile servire i file in modo programmatico in caso di necessità, magari per servire file crittografati come quelli posti in questa domanda .
Bogdan,

53

Un'opzione sarebbe quella di creare un collegamento simbolico tra una sottocartella nella directory di archiviazione e nella directory pubblica.

Per esempio

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

Questo è anche il metodo utilizzato da Envoyer , un gestore di distribuzione creato da Taylor Otwell, lo sviluppatore di Laravel.


Sono un po 'nuovo in questo. Questo deve essere eseguito sul terminale o essere definito in un file di configurazione da qualche parte in laravel?
Gaurav Mehta,

sì, devi eseguirlo tramite la riga di comando. Dovrebbe essere configurato ovunque tu distribuisca l'app.
SlateEntropy

Per gli utenti Windows, ecco uno strumento autonomo per questo se non si desidera utilizzare CMD: github.com/amd989/Symlinker#downloads
David

3
La domanda chiedeva come mostrare gli avatar degli utenti archiviati storagepubblicamente, di solito gli avatar non richiedono alcun tipo di controllo degli accessi. Se non è richiesta alcuna sicurezza utilizzando qualsiasi tipo di middleware o route è solo uno spreco di risorse. Vale anche la pena notare dal momento che Laravel 5.2 esiste un "disco" di file separato per i file pubblici ( laravel.com/docs/5.2/filesystem ) utilizzando i collegamenti simbolici.
SlateEntropy,

6
C'è un comando artigianale per farlo in Laravel 5.3: $ php archiviazione artigianale: link
Phil

22

Secondo i documenti di Laravel 5.2, i file accessibili al pubblico dovrebbero essere inseriti nella directory

storage/app/public

Per renderli accessibili dal Web, è necessario creare un collegamento simbolico da public/storagea storage/app/public.

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

Ora puoi creare nella tua vista un URL per i file usando l'assistente risorse:

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


13

Prima di tutto devi creare un collegamento simbolico per la directory di archiviazione usando il comando artisan

php artisan storage:link

Quindi, in qualsiasi vista, puoi accedere alla tua immagine tramite l'URL helper in questo modo.

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

4

È bene salvare tutte le immagini e i documenti privati ​​nella directory di archiviazione, quindi avrai il pieno controllo sull'etere del file e potrai consentire a determinati tipi di utenti di accedere al file o limitare.

Crea un percorso / documenti e punta a qualsiasi metodo del controller:

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

Quando si preme il localhost:8000/docsfile verrà scaricato se esiste.

Il file deve essere nella root/storage/app/users/documentsdirectory in base al codice sopra, questo è stato testato Laravel 5.4.


4

Se si desidera caricare un numero limitato di immagini private È possibile codificare le immagini in base64 ed eseguirne l'eco <img src="{{$image_data}}">direttamente in:

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

Ho parlato di privato perché dovresti usare questi metodi solo se non vuoi archiviare immagini accessibili pubblicamente tramite url, invece devi sempre usare il modo standard (collega l'archiviazione / cartella pubblica e servi le immagini con il server HTTP).

Fai attenzione alla codifica per base64()avere due lati negativi importanti:

  1. Ciò aumenterà le dimensioni dell'immagine di circa il 30%.
  2. Combini tutte le dimensioni delle immagini in una richiesta, invece di caricarle in parallelo, questo non dovrebbe essere un problema per alcune miniature, ma per molte immagini evita di usare questo metodo.

2

Se stai usando php, usa semplicemente la funzione php symlink, come segue:

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

cambia il nome utente e il nome del progetto con i nomi giusti.


1

senza nome del sito

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

se si desidera aggiungere il nome del sito al suo esempio da aggiungere su api JSON felids

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

0

Se sei come me e in qualche modo hai percorsi di file completi (ho fatto una corrispondenza del modello glob () sulle foto richieste, quindi finisco praticamente con percorsi di file completi) e la tua configurazione di archiviazione è ben collegata (cioè tale che i tuoi percorsi avere la stringa storage/app/public/), quindi puoi usare il mio piccolo trucco sporco qui sotto: 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

Se il disco 'local' non funziona per te, prova questo:

  1. Cambia locale in pubblico 'default' => env('FILESYSTEM_DRIVER', 'public'),daproject_folder/config/filesystem.php
  2. Cancella la cache di configurazione php artisan config:clear
  3. Quindi creare un collegamento sym php artisan storage:link

Per ottenere l'URL dell'immagine caricata è possibile utilizzare questo Storage::url('iamge_name.jpg');

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.