Wie erhalte ich den Dateipfad mithilfe der Speicherfassade in Laravel 5?

82

Ich habe mit der neuen Flysystem-Integration in Laravel 5 experimentiert. Ich speichere 'lokalisierte' Pfade zur Datenbank und lasse die Speicherfassade den Pfad vervollständigen. Zum Beispiel speichere screenshots/1.jpgund benutze ich

Storage::disk('local')->get('screenshots/1.jpg')

oder

Storage::disk('s3')->get('screenshots/1.jpg') 

Ich kann dieselbe Datei auf verschiedenen Datenträgern abrufen.

get Ruft den Dateiinhalt ab, aber ich hoffe, ihn in meinen Ansichten wie folgt verwenden zu können:

<img src="{{ Storage::path('screenshots/1.jpg') }}" />

Ein Pfad oder irgendetwas, das den vollständigen Pfad abrufen kann, ist jedoch nicht verfügbar (soweit ich sehen kann). Wie kann ich den vollständigen Pfad zurückgeben? Oder frage ich mich, ob dies beabsichtigt ist? Wenn ja, warum sollte ich nicht in der Lage sein, den vollen Weg zu finden? Oder gehe ich das völlig falsch an?

Daviestar
quelle
1
Sie fragen nach der URL und nicht nach dem Pfad.
Adam

Antworten:

54

Bearbeiten: Lösung für L5.2 +

Es gibt eine bessere und einfachere Lösung.

Verwenden Sie Storage::url($filename)diese Option , um den vollständigen Pfad / die URL einer bestimmten Datei abzurufen. Beachten Sie, dass Sie S3als Speicherdateisystem Folgendes festlegen müssen config/filesystems.php:'default' => 's3'

Natürlich können Sie dies auch Storage::disk('s3')->url($filename)auf die gleiche Weise tun .

Wie Sie sehen können, config/filesystems.phpist auch ein Parameter 'cloud' => 's3'definiert, der sich auf das Cloud-Dateisystem bezieht. Für den Fall, dass Sie den Speicherordner auf dem lokalen Server beibehalten möchten, aber einige Dateien in der Cloud abrufen / speichern möchten, verwenden Sie Storage::cloud()auch dieselben Dateisystemmethoden, z Storage::cloud()->url($filename).

In der Laravel-Dokumentation wird diese Methode nicht erwähnt. Wenn Sie jedoch mehr darüber erfahren möchten, können Sie den Quellcode hier überprüfen .

Pere Joan Martorell
quelle
nett! Dies ist eine neue Methode , aber ich bin froh, dass sie jetzt hier ist! Funktioniert die Speicherklasse standardmäßig in Ansichten? Wenn ja, markieren Sie dies als die richtige Antwort.
Daviestar
Ja! Es funktioniert standardmäßig in Ihren Ansichten, sodass Sie sich darüber überhaupt keine Sorgen machen müssen.
Pere Joan Martorell
5
Dies ist für L5.2 +
Daviestar
153

Der Pfad zu Ihrer Speicherfestplatte lautet:

$storagePath  = Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix()

Ich kenne keine kürzeren Lösungen dafür ...

Sie können den $ storagePath für Ihre Ansichten freigeben und dann einfach aufrufen

$storagePath."/myImg.jpg";
schock_gone_wild
quelle
Dies ist die perfekte Lösung, um den Pfad des öffentlichen Speicherordners abzurufen. Vielen Dank!
David
14
Eine andere Möglichkeit ist, applyPathPrefixwie folgt zu verwenden :Storage::disk('local')->getDriver()->getAdapter()->applyPathPrefix('myImg.jpg');
Maxim Lanin
3
@maximLanin: Wenn Sie Ihr Beispiel kopieren, hat das letzte (applyPathPrefix) ein seltsames Zeichen zwischen h und P (Pfad * Präfix). Wenn Sie das kopieren und einfügen, wird eine Fehlermeldung angezeigt. Das erste können applyPathPrefixSie kopieren. Sehr eigenartig. (Sie können es testen, indem Sie auf den letzten Methodennamen in Ihrem Beispiel
Maurice
3
getDriver()wird nicht gebraucht. Einfach Storage::disk('local')->getAdapter()->getPathPrefix()wird auch funktionieren.
RA.
6
Vielleicht gut zu wissen, dass es seit Laravel 5.4 eine neue, einfache Methode gibt Storage::path, siehe Bilals Antwort
Marten Koetsier
69

Diese Methode gibt es seit Laravel 5.4. Sie können sie erhalten durch:

$path = Storage::disk('public')->path($filename);
Bilal Gultekin
quelle
1
Funktioniert wie ein Zauber in Laravel 5.6. Wenn sich jemand über dieses in der API wundert, ist es hier: laravel.com/api/5.6/Illuminate/Filesystem/…
Angel Santiago Jaime Zavala
1
Soweit ich sehen kann, existiert diese Methode seit Laravel 5.4 ( laravel.com/api/5.4/Illuminate/Filesystem/… )
Marten Koetsier
Beide Links in den beiden obigen Kommentaren sind tot.
dotNET
9

So habe ich es zum Laufen gebracht - mit einer Umgebungsvariablen zwischen s3- und lokalen Verzeichnispfaden wechseln und den Pfad an alle Ansichten übergeben.

In .env:

APP_FILESYSTEM=local or s3
S3_BUCKET=BucketID

In config / filesystems.php:

'default' => env('APP_FILESYSTEM'),

In app/Providers/AppServiceProvider:

public function boot()
{
    view()->share('dynamic_storage', $this->storagePath());
}

protected function storagePath()
{
    if (Storage::getDefaultDriver() == 's3') {
        return Storage::getDriver()
                ->getAdapter()
                ->getClient()
                ->getObjectUrl(env('S3_BUCKET'), '');
    }

    return URL::to('/');
}
Daviestar
quelle
1
Die Verwendung des s3-Speichers wie beschrieben hat einen Fehler für mich generiert. Also habe ich das Beispiel dahingehend geändert return Storage::disk('s3')->getDriver()->getAdapter()->getClient()->getObjectUrl(env('S3_BUCKET'), '').'/';
Lionel Morrison
4

Nun, vor Wochen habe ich eine sehr ähnliche Frage gestellt ( CDN-URL aus hochgeladener Datei über Speicher abrufen ): Ich wollte, dass die CDN-URL das Bild in meiner Ansicht anzeigt (wie Sie es benötigen).

Nach Überprüfung der Paket-API habe ich jedoch bestätigt, dass diese Aufgabe nicht ausgeführt werden kann. Meine Lösung bestand also darin, die Verwendung zu vermeiden flysystem. In meinem Fall musste ich mit RackSpace spielen. Entscheiden Sie sich schließlich, mein Verwendungspaket zu erstellen und mein eigenes Speicherpaket mit dem PHP SDK für OpenStack zu erstellen .

Auf diese Weise haben Sie vollen Zugriff auf Funktionen, die Sie benötigen getPublicUrl(), um die öffentliche URL aus einem CDN-Container abzurufen:

/** @var DataObject $file */
$file = \OpenCloud::container('cdn')->getObject('screenshots/1.jpg');

// $url:  https://d224d291-8316ade.ssl.cf1.rackcdn.com/screenshots/1.jpg
$url = (string) $file->getPublicUrl(UrlType::SSL);

Zusammenfassend lässt sich sagen, dass flysystemes nicht ausreicht , den Speicherdienst auf eine andere Ebene zu heben . Zu diesem localZweck können Sie die Lösung von @ nXu ausprobieren

Manix
quelle
4

Holen Sie sich zuerst die Datei-URL / den Link und dann den Pfad wie folgt:

$url = Storage::disk('public')->url($filename);
$path = public_path($url);
Filius
quelle
4

Wenn Sie nur den Speicherpfad (Festplattenpfad) anzeigen möchten, verwenden Sie Folgendes:

Storage::disk('local')->url('screenshots/1.jpg'); // storage/screenshots/1.jpg
Storage::disk('local')->url(''): // storage

Wenn Sie interessiert sind, habe ich ein Paket ( https://github.com/fsasvari/laravel-uploadify ) nur für Laravel erstellt, damit Sie alle diese Felder in eloquenten Modellfeldern verwenden können:

$car = Car::first();

$car->upload_cover_image->url();
$car->upload_cover_image->name();
$car->upload_cover_image->basename();
$car->upload_cover_image->extension();
$car->upload_cover_image->filesize();
fsasvari
quelle
3

Wenn Sie eine absolute URL der Datei benötigen, verwenden Sie den folgenden Code:

$file_path = \Storage::url($filename);
$url = asset($file_path);
// Output: http://example.com/storage/filename.jpg
Arvind Bhardwaj
quelle
2

Speichermethode:

public function upload($img){
   $filename = Carbon::now() . '-' .  $img->getClientOriginalName();
   return Storage::put($filename, File::get($img)) ? $filename : '';
}

Route:

 Route::get('image/{filename}', [
        'as'   => 'product.image',
        'uses' => 'ProductController@getImage',
    ]);

Regler:

 public function getImage($filename)
    {
        $file = Storage::get($filename);

        return new Response($file, 200);
    }

Aussicht:

 <img src="{{ route('product.image', ['filename' => $yourImageName]) }}" alt="your image"/>
MevlütÖzdemir
quelle
warum sollte jemand das tun, warum mit s3 dann broxy es auf dem Webserver !!
Shady Keshk
2

Eine andere Lösung, die ich gefunden habe, ist folgende:

Storage::disk('documents')->getDriver()->getConfig()->get('url')

Gibt die URL mit dem Basispfad des Dokumentenspeichers zurück

Marc Garcia
quelle
1

Sehen Sie sich Folgendes an: So verwenden Sie storage_path (), um ein Bild in Laravel 4 anzuzeigen . Gleiches gilt für Laravel 5:

Der Speicher ist für das Dateisystem bestimmt und der größte Teil davon ist für den Webserver nicht zugänglich. Die empfohlene Lösung besteht darin, die Bilder beispielsweise im öffentlichen Ordner (dem Dokumentstamm) zu speichern public/screenshots/. Wenn Sie sie dann anzeigen möchten, verwenden Sie asset('screenshots/1.jpg').

nXu
quelle
Ich versuche, eine 'Festplatte' als meinen öffentlichen Ordner während der Entwicklung und s3 als live
einzurichten
Es spielt keine Rolle, Storage::path()gibt den Pfad der Datei auf Ihrem Server zurück, aber Sie benötigen eine URL dazu und der Webserver kann nur Dateien aus Ihrem Dokumentenstamm bereitstellen <project>/public. Erstellen Sie Ihre Verzeichnisse darin und verwenden Sie url()oder asset()in den Blade-Vorlagen.
nXu
2
Storage::path()existiert nicht, ich möchte es aber
Daviestar
Okay, ich habe es falsch verstanden, sorry. Was ich tun würde, ist immer noch dasselbe: Speichern Sie den vollständigen Pfad zur Datenbank, sei es lokal oder s3. Überprüfen Sie beim Hochladen / Erstellen von Bildern einfach getenv('debug'), welche Bilder verwendet werden sollen.
nXu
Ich habe versucht zu vermeiden, den vollständigen Pfad zu speichern, aber vielleicht ist es der sinnvollste Weg.
Daviestar
1

In meinem Fall habe ich eine separate Methode für lokale Dateien erstellt: src / Illuminate / Filesystem / FilesystemAdapter.php

    /**
 * Get the local path for the given filename.
 * @param $path
 * @return string
 */
public function localPath($path)
{
    $adapter = $this->driver->getAdapter();
    if ($adapter instanceof LocalAdapter) {
        return $adapter->getPathPrefix().$path;
    } else {
        throw new RuntimeException('This driver does not support retrieving local path');
    }
}

dann erstelle ich eine Pull-Anfrage an das Framework, aber es ist noch nicht in den Hauptkern integriert: https://github.com/laravel/framework/pull/13605 Kann jemand diese zusammenführen))

Ruslan Terekhov
quelle
0

Diese Arbeit für mich im Jahr 2020 bei Laravel 7

        $image_resize = Image::make($image->getRealPath());
        $image_resize->resize(800,600);
        $image_resize->save(Storage::disk('episodes')->path('') . $imgname);

so können Sie es so verwenden

echo Storage::disk('public')->path('');
Ahmad Odeh
quelle