Jak uzyskać adres URL pliku za pomocą fasady magazynu w Laravel 5?

83

Eksperymentowałem z nową integracją Flysystem z Laravel 5. Przechowuję „zlokalizowane” ścieżki do bazy danych i uzyskuję fasadę Storage, aby ukończyć ścieżkę. Na przykład przechowuję screenshots/1.jpgi używam

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

lub

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

Mogę pobrać ten sam plik na różnych dyskach.

get pobiera zawartość pliku, ale mam nadzieję, że wykorzystam ją w moich widokach w następujący sposób:

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

ale ścieżka lub cokolwiek, co może odzyskać pełną ścieżkę, nie jest dostępne (o ile widzę). Jak więc mogę zwrócić pełną ścieżkę? A może zastanawiam się, czy jest to zgodne z projektem? Jeśli tak, dlaczego nie powinienem być w stanie uzyskać pełnej ścieżki? Czy też podchodzę do tego całkowicie w niewłaściwy sposób?

daviestar
źródło
1
Pytasz o adres URL, a nie o ścieżkę.
Adam

Odpowiedzi:

54

Edycja: rozwiązanie dla L5.2 +

Jest lepsze i prostsze rozwiązanie.

Użyj, Storage::url($filename)aby uzyskać pełną ścieżkę / adres URL danego pliku. Zauważ, że musisz ustawić S3jako system plików do przechowywania w config/filesystems.php:'default' => 's3'

Oczywiście możesz też zrobić Storage::disk('s3')->url($filename)w ten sam sposób.

Jak widać , zdefiniowano config/filesystems.phprównież parametr 'cloud' => 's3'odnoszący się do systemu plików Cloud. W przypadku, gdy chcesz zachować folder przechowywania na serwerze lokalnym, ale pobierać / przechowywać niektóre pliki w chmurze, skorzystaj z Storage::cloud()tych samych metod systemu plików, tj Storage::cloud()->url($filename).

Dokumentacja Laravela nie wspomina o tej metodzie, ale jeśli chcesz dowiedzieć się o niej więcej, możesz sprawdzić jej kod źródłowy tutaj .

Pere Joan Martorell
źródło
miły! to jest nowa metoda , ale cieszę się, że jest tutaj teraz! Czy klasa Storage działa domyślnie w widokach? Jeśli tak, oznaczy to jako poprawną odpowiedź.
daviestar
tak! domyślnie działa w Twoich widokach, więc nie musisz się o to martwić.
Pere Joan Martorell
5
To jest dla L5.2 +
daviestar
154

Ścieżka do twojego dysku magazynującego byłaby następująca:

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

Nie znam krótszych rozwiązań ...

Możesz udostępnić $ storagePath swoim Widokom, a następnie po prostu zadzwonić

$storagePath."/myImg.jpg";
shock_gone_wild
źródło
Jest to idealne rozwiązanie, aby uzyskać ścieżkę do folderu publicznego. Dzięki!
David,
14
Innym sposobem jest użycie w applyPathPrefixten sposób:Storage::disk('local')->getDriver()->getAdapter()->applyPathPrefix('myImg.jpg');
Maxim Lanin
3
@maximLanin: W jakiś sposób, jeśli skopiujesz swój przykład, ostatni (applyPathPrefix) ma dziwny znak między h i P (ścieżka * prefiks). Jeśli skopiujesz to i wkleisz, pojawi się błąd. Pierwszy, applyPathPrefixktóry możesz skopiować. Bardzo dziwny. (możesz to sprawdzić, klikając dwukrotnie ostatnią nazwę metody w swoim przykładzie.
Maurice,
3
getDriver()nie jest potrzebne. Po prostu też Storage::disk('local')->getAdapter()->getPathPrefix()zadziała.
RA.
6
Być może dobrze wiedzieć, że od Laravel 5.4 istnieje nowa, prosta metoda Storage::path, patrz odpowiedź Bilala
Marten Koetsier
9

Tak to działało - przełączanie się między s3 a ścieżkami do katalogu lokalnego ze zmienną środowiskową, przekazywanie ścieżki do wszystkich widoków.

W .env:

APP_FILESYSTEM=local or s3
S3_BUCKET=BucketID

W config / filesystems.php:

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

W 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
źródło
1
Korzystanie z pamięci s3 zgodnie z opisem wygenerowało dla mnie błąd. Więc poprawiłem ten przykład return Storage::disk('s3')->getDriver()->getAdapter()->getClient()->getObjectUrl(env('S3_BUCKET'), '').'/';
Lionel Morrison
5

Najpierw pobierz adres URL / link, a następnie ścieżkę, jak poniżej:

$url = Storage::disk('public')->url($filename);
$path = public_path($url);
filius
źródło
5

Jeśli chcesz tylko wyświetlić ścieżkę przechowywania (dysku), użyj tego:

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

Ponadto, jeśli jesteś zainteresowany, stworzyłem pakiet ( https://github.com/fsasvari/laravel-uploadify ) tylko dla Laravel, abyś mógł używać wszystkich tych pól na polach modelu Eloquent:

$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
źródło
4

Cóż, kilka tygodni temu zadałem bardzo podobne pytanie ( Uzyskaj adres URL CDN z przesłanego pliku przez Magazyn ): Chciałem, aby adres URL CDN wyświetlał obraz w moim widoku (zgodnie z wymaganiami).

Jednak po przejrzeniu API pakietu stwierdziłem, że nie da się tego zrobić. Więc moim rozwiązaniem było unikanie używania flysystem. W moim przypadku potrzebowałem grać z RackSpace. Ostatecznie zdecyduj się więc na stworzenie mojego pakietu użytkowego i stworzenie własnego pakietu przechowywania przy użyciu zestawu PHP SDK dla OpenStack .

W ten sposób masz pełny dostęp do funkcji, których potrzebujesz getPublicUrl(), aby uzyskać publiczny adres URL z kontenera cdn:

/** @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);

Podsumowując, jeśli trzeba przenieść usługę przechowywania na inny poziom, flysystemto nie wystarczy. Do localcelów możesz wypróbować rozwiązanie @ nXu

manix
źródło
3

Jeśli potrzebujesz bezwzględnego adresu URL pliku, użyj poniższego kodu:

$file_path = \Storage::url($filename);
$url = asset($file_path);
// Output: http://example.com/storage/filename.jpg
Arvind Bhardwaj
źródło
2

Sposób przechowywania:

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

Trasa:

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

Kontroler:

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

        return new Response($file, 200);
    }

Widok:

 <img src="{{ route('product.image', ['filename' => $yourImageName]) }}" alt="your image"/>
MevlütÖzdemir
źródło
po co ktoś miałby to robić, po co używać s3, a potem broxy go na serwerze WWW !!
Shady Keshk
2

Inne rozwiązanie, które znalazłem, to:

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

Zwróci adres URL z podstawową ścieżką przechowywania dokumentów

Marc Garcia
źródło
1

Spójrz na to: Jak używać metody storage_path () do przeglądania obrazu w programie laravel 4 . To samo dotyczy Laravel 5:

Pamięć masowa jest przeznaczona dla systemu plików, a większa jej część nie jest dostępna dla serwera WWW. Zalecanym rozwiązaniem jest przechowywanie obrazów gdzieś w folderze publicznym (którym jest katalog główny dokumentu), public/screenshots/na przykład. Następnie, jeśli chcesz je wyświetlić, użyj asset('screenshots/1.jpg').

nXu
źródło
Próbuję ustawić
``
To naprawdę nie ma znaczenia, Storage::path()zwraca ścieżkę do pliku na twoim serwerze, ale potrzebujesz do niego adresu URL, a serwer internetowy może obsługiwać tylko pliki z katalogu głównego twojego dokumentu, czyli <project>/public. Utwórz w nim swoje katalogi i użyj url()lub asset()w szablonach ostrzy.
nXu
2
Storage::path()nie istnieje, chciałbym jednak
daviestar
Okej, źle zrozumiałem, przepraszam. To, co bym zrobił, jest nadal takie samo: zapisz pełną ścieżkę do bazy danych, czy to lokalną, czy s3. Podczas przesyłania / tworzenia obrazów po prostu sprawdź getenv('debug')i zdecyduj, którego użyć.
nXu
Starałem się nie oszczędzać całej ścieżki, ale może jest to najbardziej rozsądna droga.
daviestar
1

W moim przypadku stworzyłem oddzielną metodę dla plików lokalnych, w tym pliku: 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');
    }
}

następnie tworzę pull request do frameworka, ale nadal nie został on scalony z głównym rdzeniem: https://github.com/laravel/framework/pull/13605 Może ktoś scalić ten))

Rusłan Terekhov
źródło
0

ta praca dla mnie w 2020 roku w laravel 7

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

więc możesz go używać w ten sposób

echo Storage::disk('public')->path('');
Ahmad Odeh
źródło