Как получить URL-адрес файла с помощью фасада хранилища в laravel 5?


83

Я экспериментировал с использованием новой интеграции 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-адрес, а не путь.
Адам

Ответы:


54

Изменить: решение для 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 этот метод не упоминается, но если вы хотите узнать о нем больше, вы можете проверить его исходный код здесь .


отлично! это новый метод , но я рад, что он теперь здесь! Работает ли класс Storage в представлениях по умолчанию? Если да, отметьте это как правильный ответ.
daviestar 05

да! он работает в ваших представлениях по умолчанию, так что вам вообще не о чем беспокоиться.
Pere Joan Martorell

5
Это для L5.2 +
daviestar

154

Путь к вашему диску для хранения будет следующим:

$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/…
Ангел Сантьяго Хайме Завала

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'), '').'/';
Лайонел Моррисон

5

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

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

5

Если вы просто хотите отобразить путь к хранилищу (диску), используйте это:

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

Кроме того, если вам интересно, я создал пакет ( https://github.com/fsasvari/laravel-uploadify ) только для Laravel, чтобы вы могли использовать все эти поля в полях модели 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();

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, а затем передавать его на веб-сервер !!
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.