Як отримати URL-адресу файлу за допомогою фасаду зберігання в Laravel 5?


84

Я експериментував, використовуючи нову інтеграцію Flysystem з Laravel 5. Я зберігаю "локалізовані" шляхи до БД і отримую фасад Storage для завершення шляху. Наприклад, я зберігаю screenshots/1.jpgта використовую

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

або

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

Я можу отримати той самий файл на різних дисках.

get отримує вміст файлу, але я сподіваюся використовувати його в своїх поданнях, як це:

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

але шлях, або що-небудь, що може отримати повний шлях, недоступний (наскільки я бачу). То як я можу повернути повний шлях? Або мені цікаво, чи це за задумом? Якщо так, то чому я не маю змоги отримати повний шлях? Або я роблю це зовсім не так?


1
Ви запитуєте URL-адресу, а не шлях.
Адам

Відповіді:


55

Редагувати: Рішення для L5.2 +

Існує краще і простіше рішення.

Використовуйте Storage::url($filename)для отримання повного шляху / URL-адреси даного файлу. Зверніть увагу, що вам потрібно встановити S3як вашу файлову систему зберігання в config/filesystems.php:'default' => 's3'

Звичайно, ви можете робити Storage::disk('s3')->url($filename)так само.

Як ви можете бачити, config/filesystems.phpтам також 'cloud' => 's3'визначено параметр , який відноситься до файлової системи Cloud. Якщо ви хочете зберегти папку зберігання на локальному сервері, але отримати / зберегти деякі файли у хмарі Storage::cloud(), яка також має ті самі методи файлової системи, тобто Storage::cloud()->url($filename).

Документація Laravel не згадує про цей метод, але якщо ви хочете дізнатись більше про нього, ви можете перевірити його вихідний код тут .


приємно! це новий метод , але я радий, що він зараз тут! Чи працює клас зберігання у поданнях за замовчуванням? Якщо так, то позначить це як правильну відповідь.
daviestar

так! він працює у ваших поданнях за замовчуванням, тому вам не доведеться про це турбуватися взагалі.
Пере Джоан Марторелл

5
Це для L5.2 +
daviestar

155

Шлях до вашого диска зберігання буде таким:

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

Я не знаю більш коротких рішень цього ...

Ви можете поділитися $ storagePath зі своїми поданнями, а потім просто зателефонувати

$storagePath."/myImg.jpg";

Це ідеальне рішення, щоб отримати шлях до папки загального зберігання. Дякую!
Девід

14
Інший спосіб - вживати applyPathPrefixтак:Storage::disk('local')->getDriver()->getAdapter()->applyPathPrefix('myImg.jpg');
Максим Ланін

3
@maximLanin: Якось, якщо ви копіюєте свій приклад, останній (applyPathPrefix) має дивний символ між h та P (префікс шляху *). Якщо скопіювати вставку, ви отримаєте повідомлення про помилку. Перший applyPathPrefixви можете скопіювати. Дуже дивно. (Ви можете перевірити це, двічі клацнувши назву останнього методу у вашому прикладі.
Моріс,

3
getDriver()не потрібен. Просто Storage::disk('local')->getAdapter()->getPathPrefix()буде працювати також.
РА.

6
Можливо, добре знати, що з часу Laravel 5.4 існує новий простий метод Storage::path, див . Відповідь Білала
Marten Koetsier

69

Цей метод існує з Laravel 5.4, отримати його можна:

$path = Storage::disk('public')->path($filename);

1
Працює як шарм у Laravel 5.6. Якщо хтось задається питанням про це в API, ось воно: laravel.com/api/5.6/Illuminate/Filesystem/…
Angel Santiago Jaime Zavala

1
Наскільки я бачу, цей метод існує з Laravel 5.4 ( laravel.com/api/5.4/Illuminate/Filesystem/… )
Marten Koetsier

Обидва посилання у цих двох коментарях мертві.
dotNET

9

Ось як я змусив це працювати - перемикаючись між s3 та локальними шляхами каталогів зі змінною середовища, передаючи шлях усім представленням.

У .env:

APP_FILESYSTEM=local or s3
S3_BUCKET=BucketID

У config / filesystems.php:

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

В 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('/');
}

1
Використання сховища s3, як описано, створило для мене помилку. Тож я змінив приклад до цього return Storage::disk('s3')->getDriver()->getAdapter()->getClient()->getObjectUrl(env('S3_BUCKET'), '').'/';
Лайонел Моррісон

6

Якщо ви просто хочете відобразити шлях до сховища (диска), скористайтеся цим:

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

Крім того, якщо вам цікаво, я створив пакет ( https://github.com/fsasvari/laravel-uploadify ) саме для Laravel, щоб ви могли використовувати всі ці поля в полях Eloquent model:

$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();

5

Спочатку отримайте URL-адресу / посилання на файл, а потім шлях, як показано нижче:

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

4

Ну, кілька тижнів тому я зробив дуже подібне запитання ( отримати URL-адресу CDN із завантаженого файлу через сховище ): я хотів, щоб URL-адреса CDN відображала зображення на моєму погляді (як ви вимагаєте).

Однак, переглянувши API пакета, я підтвердив, що неможливо виконати це завдання. Отже, моє рішення було уникати використання flysystem. У моєму випадку мені потрібно було пограти з RackSpace. Отже, нарешті, вирішіть створити мій пакет використання та створити власний пакет зберігання, використовуючи PHP SDK для OpenStack .

Таким чином, у вас є повний доступ до функцій, які вам потрібні getPublicUrl(), щоб отримати загальнодоступну URL-адресу з контейнера 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);

На закінчення: якщо потрібно вивести послугу зберігання на інший рівень, цього flysystemнедостатньо. Для localцілей ви можете спробувати рішення @ nXu


3

Якщо вам потрібна абсолютна URL-адреса файлу, використовуйте код нижче:

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

2

Спосіб зберігання:

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

Маршрут:

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

Контролер:

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

        return new Response($file, 200);
    }

Вид:

 <img src="{{ route('product.image', ['filename' => $yourImageName]) }}" alt="your image"/>

навіщо хтось це робити, навіщо використовувати s3, а потім broxy його на веб-сервері !!
Shady Keshk,

2

Я знайшов ще одне рішення:

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

Поверне URL-адресу з базовим шляхом зберігання документів


1

Погляньте на це: Як використовувати storage_path () для перегляду зображення в laravel 4 . Те саме стосується Laravel 5:

Сховище призначене для файлової системи, і більша частина його недоступна для веб-сервера. Рекомендованим рішенням є зберігання зображень десь у загальній папці (яка є коренем документа), public/screenshots/наприклад. Потім, коли ви хочете відобразити їх, використовуйте asset('screenshots/1.jpg').


Я намагаюся встановити `` диск '', який буде моєю загальнодоступною папкою під час розробки та s3 під час роботи
daviestar

Це насправді не має значення, Storage::path()повертає шлях до файлу на вашому сервері, але вам потрібна URL-адреса, і веб-сервер може обслуговувати файли лише з кореня вашого документа, який є <project>/public. Створіть свої каталоги всередині нього та використовуйте url()або asset()в шаблонах леза.
nXu

2
Storage::path()не існує, я хотів би, щоб це
daviestar

Гаразд, я неправильно зрозумів, вибачте. Те, що я б зробив, все те саме: збережіть повний шлях до БД, будь то локальний чи s3. Завантажуючи / створюючи зображення, просто перевірте getenv('debug')і вирішіть, який із них використовувати.
nXu

Я намагався уникнути збереження повного шляху, але, можливо, це найбільш розумний шлях.
daviestar

1

У моєму випадку я зробив окремий метод для локальних файлів, у цьому файлі: 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');
    }
}

тоді я створюю запит на витягування до фреймворку, але він все ще не об’єднаний в основне ядро: https://github.com/laravel/framework/pull/13605 Може хтось об’єднає цей))


0

ця робота для мене в 2020 році на laravel 7

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

так що ви можете використовувати його таким чином

echo Storage::disk('public')->path('');
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.