Laravel 5 - Wie greife ich auf Bilder zu, die im Speicher in View hochgeladen wurden?

171

Ich habe Benutzeravatare im Laravel-Speicher hochgeladen. Wie kann ich darauf zugreifen und sie in einer Ansicht rendern?

Der Server verweist auf alle Anforderungen. /publicWie kann ich sie anzeigen, wenn sie sich im /storageOrdner befinden?

Tadeáš Jílek
quelle

Antworten:

349

Der beste Ansatz besteht darin, einen symbolischen Link wie @SlateEntropy zu erstellen , auf den in der folgenden Antwort sehr gut hingewiesen wird . Um dies zu unterstützen, enthält Laravel seit Version 5.3 einen Befehl, der dies unglaublich einfach macht:

php artisan storage:link

Das schafft einen Symlink von public/storagebis zu storage/app/publicfür Sie und das ist alles, was dazu gehört. Jetzt kann auf jede Datei in /storage/app/publicüber einen Link zugegriffen werden wie:

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

Wenn Sie aus irgendeinem Grund keine symbolischen Links erstellen können (möglicherweise verwenden Sie Shared Hosting usw.) oder einige Dateien hinter einer Zugriffssteuerungslogik schützen möchten, gibt es die Alternative, eine spezielle Route zu haben, die und liest dient dem Bild. Zum Beispiel eine einfache Schließungsroute wie diese:

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

Sie können jetzt wie bei einem Symlink auf Ihre Dateien zugreifen:

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

Wenn Sie die Interventionsbildbibliothek verwenden , können Sie die integrierte responseMethode verwenden, um die Dinge prägnanter zu gestalten:

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

WARNUNG

Beachten Sie, dass durch das manuelle Bereitstellen der Dateien eine Leistungseinbuße entsteht , da Sie den gesamten Lebenszyklus von Laravel-Anforderungen durchlaufen, um den Dateiinhalt zu lesen und zu senden. Dies ist erheblich langsamer als der HTTP-Server.

Bogdan
quelle
Das scheint gut zu sein. Ich möchte noch eine Frage stellen. Wird empfohlen, Dateien wie Avatare, Daumen usw. (hochgeladene Dateien von Benutzern) im Speicher zu speichern?
Tadeáš Jílek
5
Sie können sie speichern, wo immer Sie möchten, aber es sei denn, es handelt sich um private Dateien. Ich denke, Sie sollten sie besser im publicVerzeichnis speichern . Auf diese Weise vermeiden Sie den Aufwand, eine Image-Antwort erstellen zu müssen, die vom HTTP-Server viel schneller verarbeitet werden kann.
Bogdan
2
Persönlich würde ich Benutzerdateien nicht im öffentlichen Ordner speichern. Ich finde die Dinge viel aufgeräumter und übersichtlicher, wenn der Speicherordner für die Speicherung verwendet wird.
SlateEntropy
2
Ich würde beides nicht empfehlen, da Sie dann den Aufwand für das erneute Laden von Laravel und / oder die Nutzung von PHP zum Lesen jedes Bildes erhöhen. Die Verwendung eines von CmdSft beschriebenen Symlinks wäre viel schneller.
user1960364
4
@ user1960364 Aus diesem Grund wird im letzten Absatz dringend empfohlen, den Symlink-Ansatz zu verwenden. Die Antwort selbst ist zwar unter Leistungsgesichtspunkten nicht die beste Lösung, sie ist jedoch weiterhin gültig und möglicherweise der einzige Ansatz für Benutzer, die Apps auf gemeinsam genutzten Servern ausführen, auf denen Symlinks möglicherweise nicht eingerichtet werden können. Die Antwort zeigt auch, wie Sie Dateien programmgesteuert bereitstellen können, falls dies jemals erforderlich sein sollte, z. B. um verschlüsselte Dateien bereitzustellen, wie in dieser Frage gestellt .
Bogdan
53

Eine Möglichkeit besteht darin, eine symbolische Verknüpfung zwischen einem Unterordner in Ihrem Speicherverzeichnis und einem öffentlichen Verzeichnis herzustellen.

Beispielsweise

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

Dies ist auch die Methode von Envoyer , einem Deployment Manager, der von Taylor Otwell, dem Entwickler von Laravel, entwickelt wurde.

SlateEntropy
quelle
Ich bin ein bisschen neu in diesem Bereich. Muss dies auf dem Terminal ausgeführt oder in einer Konfigurationsdatei irgendwo in Laravel definiert werden?
Gaurav Mehta
Ja, Sie müssen dies über die Befehlszeile ausführen. Es muss überall dort eingerichtet werden, wo Sie die App bereitstellen.
SlateEntropy
Für Windows-Benutzer ist hier ein eigenständiges Tool, wenn Sie CMD nicht verwenden möchten: github.com/amd989/Symlinker#downloads
David
3
Bei der Frage wurde gefragt, wie Benutzer-Avatare angezeigt werden sollen, die storageöffentlich gespeichert sind. In der Regel benötigen Avatare keine Zugriffskontrolle. Wenn keine Sicherheit erforderlich ist, ist die Verwendung von Middleware oder Route nur eine Verschwendung für Ihre Ressourcen. Es ist auch erwähnenswert, dass in Laravel 5.2 eine separate Datei "Disk" für öffentliche Dateien ( laravel.com/docs/5.2/filesystem ) unter Verwendung von Symlinks vorhanden ist.
SlateEntropy
6
Es gibt einen handwerklichen Befehl, um dies in Laravel 5.3 zu tun: $ php handwerklicher Speicher: Link
Phil
22

Gemäß Laravel 5.2-Dokumenten sollten Ihre öffentlich zugänglichen Dateien in einem Verzeichnis abgelegt werden

storage/app/public

Um sie über das Web zugänglich zu machen, sollten Sie einen symbolischen Link von public/storagebis erstellen storage/app/public.

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

Jetzt können Sie in Ihrer Ansicht mithilfe des Asset-Hilfsprogramms eine URL zu den Dateien erstellen:

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

Zunächst müssen Sie mit dem Befehl artisan einen symbolischen Link für das Speicherverzeichnis erstellen

php artisan storage:link

In jeder Ansicht können Sie dann über einen URL-Helfer wie diesen auf Ihr Bild zugreifen.

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

Es ist gut, alle privaten Bilder und Dokumente im Speicherverzeichnis zu speichern, dann haben Sie die volle Kontrolle über den Dateiether, den Sie bestimmten Benutzertypen erlauben können, auf die Datei zuzugreifen oder diese einzuschränken.

Erstellen Sie eine Route / ein Dokument und zeigen Sie auf eine beliebige Controller-Methode:

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

Wenn Sie klicken, wird die localhost:8000/docsDatei heruntergeladen, falls vorhanden.

Die Datei muss sich root/storage/app/users/documentsgemäß dem obigen Code im Verzeichnis befinden, dies wurde am getestet Laravel 5.4.

Syed Shibli
quelle
4

Wenn Sie eine kleine Anzahl privater Bilder laden möchten, können Sie die Bilder in base64 codieren und <img src="{{$image_data}}">direkt wiedergeben:

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

Ich habe privat erwähnt, weil Sie diese Methoden nur verwenden sollten, wenn Sie keine Bilder speichern möchten, auf die über eine URL öffentlich zugegriffen werden kann. Stattdessen müssen Sie immer die Standardmethode verwenden (Linkspeicher / öffentlicher Ordner und Bilder mit HTTP-Server bereitstellen).

Achten Sie beim Codieren auf base64()zwei wichtige Nachteile:

  1. Dadurch wird die Bildgröße um ~ 30% erhöht.
  2. Sie kombinieren alle Bildgrößen in einer Anfrage, anstatt sie parallel zu laden. Dies sollte für einige kleine Miniaturansichten kein Problem sein, aber für viele Bilder sollten Sie diese Methode nicht verwenden.
Arash Moosapour
quelle
2

Wenn Sie PHP verwenden, verwenden Sie einfach die PHP-Symlink-Funktion wie folgt:

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

Ändern Sie den Benutzernamen und den Projektnamen in die richtigen Namen.

Dagogodboss
quelle
1

ohne Site-Namen

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

Wenn Sie dem Beispiel einen Site-Namen hinzufügen möchten, um ihn an API-JSON-Felids anzuhängen

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

Wenn Sie wie ich sind und irgendwie vollständige Dateipfade haben (ich habe einige glob () - Musterabgleiche für die erforderlichen Fotos durchgeführt, sodass ich so ziemlich vollständige Dateipfade erhalte), und Ihr Speicher-Setup ist gut verknüpft (dh Ihre Pfade habe den String storage/app/public/), dann kannst du meinen kleinen dreckigen Hack unten benutzen: 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
quelle
0

Wenn die Festplatte 'local' für Sie nicht funktioniert, versuchen Sie Folgendes:

  1. Ändern Sie lokal in öffentlich in 'default' => env('FILESYSTEM_DRIVER', 'public'),vonproject_folder/config/filesystem.php
  2. Konfigurationscache löschen php artisan config:clear
  3. Dann erstellen Sie einen Sym-Link php artisan storage:link

Um die URL des hochgeladenen Bildes zu erhalten, können Sie diese verwenden Storage::url('iamge_name.jpg');

Dnyaneshwar Harer
quelle