¿Cómo obtener la URL del archivo usando la fachada de almacenamiento en laravel 5?

82

He estado experimentando usando la nueva integración de Flysystem con Laravel 5. Estoy almacenando rutas 'localizadas' a la base de datos y obteniendo la fachada de almacenamiento para completar la ruta. Por ejemplo, almaceno screenshots/1.jpgy uso

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

o

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

Puedo recuperar el mismo archivo en diferentes discos.

get recupera el contenido del archivo, pero espero usarlo en mis vistas de esta manera:

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

pero la ruta, o cualquier cosa que pueda recuperar la ruta completa no está disponible (por lo que puedo ver). Entonces, ¿cómo puedo devolver la ruta completa? O me pregunto si esto es por diseño. Si es así, ¿por qué se supone que no puedo obtener la ruta completa? ¿O estoy haciendo esto completamente de manera incorrecta?

daviestar
fuente
1
Estás pidiendo la URL y no la ruta.
Adam

Respuestas:

54

Editar: Solución para L5.2 +

Existe una solución mejor y más sencilla.

Úselo Storage::url($filename)para obtener la ruta / URL completa de un archivo determinado. Tenga en cuenta que debe configurarlo S3como su sistema de archivos de almacenamiento en config/filesystems.php:'default' => 's3'

Por supuesto, también puedes hacerlo Storage::disk('s3')->url($filename)de la misma forma.

Como puede ver config/filesystems.php, también hay un parámetro 'cloud' => 's3'definido, que se refiere al sistema de archivos de la nube. En caso de que desee mantener la carpeta de almacenamiento en el servidor local pero recuperar / almacenar algunos archivos en la nube Storage::cloud(), use , que también tiene los mismos métodos de sistema de archivos, es decir Storage::cloud()->url($filename).

La documentación de Laravel no menciona este método, pero si quieres saber más sobre él puedes consultar su código fuente aquí .

Pere Joan Martorell
fuente
¡bonito! Este es un método nuevo , ¡pero me alegro de que esté aquí ahora! ¿La clase de almacenamiento funciona en las vistas de forma predeterminada? Si es así, marcará esta como la respuesta correcta.
daviestar
¡si! funciona en sus vistas de forma predeterminada, por lo que no tiene que preocuparse en absoluto.
Pere Joan Martorell
5
Esto es para L5.2 +
daviestar
153

La ruta a su disco de almacenamiento sería:

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

No conozco ninguna solución más corta para eso ...

Puede compartir $ storagePath con sus Vistas y luego simplemente llamar

$storagePath."/myImg.jpg";
shock_gone_wild
fuente
Esta es la solución perfecta para obtener la ruta de la carpeta de almacenamiento público. ¡Gracias!
David
14
Otra forma es usarlo applyPathPrefixasí:Storage::disk('local')->getDriver()->getAdapter()->applyPathPrefix('myImg.jpg');
Maxim Lanin
3
@maximLanin: De alguna manera, si copia su ejemplo, el último (applyPathPrefix) tiene un carácter extraño entre h y P (ruta * Prefijo). Si copia y pega eso, obtendrá un error. El primero applyPathPrefixque puedes copiar. Muy extraño. (puede probarlo haciendo doble clic en el último nombre del método en su ejemplo.
Maurice
3
getDriver()no es necesario. Simplemente Storage::disk('local')->getAdapter()->getPathPrefix()funcionará también.
RA.
6
Quizás sea bueno saber que desde Laravel 5.4 hay un método nuevo y simple Storage::path, vea la respuesta de Bilal
Marten Koetsier
69

Este método existe desde Laravel 5.4, puede obtenerlo de la siguiente manera:

$path = Storage::disk('public')->path($filename);
Bilal Gultekin
fuente
1
Funciona como un encanto en Laravel 5.6. Si alguien se pregunta acerca de este en la API, aquí está: laravel.com/api/5.6/Illuminate/Filesystem/…
Angel Santiago Jaime Zavala
1
Por lo que puedo ver, este método existe desde Laravel 5.4 ( laravel.com/api/5.4/Illuminate/Filesystem/… )
Marten Koetsier
Ambos enlaces en los dos comentarios anteriores están muertos.
dotNET
9

Así es como lo hice funcionar: cambiando entre s3 y rutas de directorio local con una variable de entorno, pasando la ruta a todas las vistas.

En .env:

APP_FILESYSTEM=local or s3
S3_BUCKET=BucketID

En config / filesystems.php:

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

En 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
fuente
1
El uso del almacenamiento s3 como se describe generó un error para mí. Así que modifiqué el ejemplo a esto return Storage::disk('s3')->getDriver()->getAdapter()->getClient()->getObjectUrl(env('S3_BUCKET'), '').'/';
Lionel Morrison
5

Primero obtenga la URL / enlace del archivo y luego la ruta, como se muestra a continuación:

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

Si solo desea mostrar la ruta de almacenamiento (disco), use esto:

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

Además, si está interesado, creé un paquete ( https://github.com/fsasvari/laravel-uploadify ) solo para Laravel para que pueda usar todos esos campos en los campos del modelo 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
fuente
4

Bueno, hace semanas hice una pregunta muy similar ( Obtener la URL de CDN del archivo subido a través de Almacenamiento ): quería que la URL de CDN mostrara la imagen en mi vista (como lo necesita).

Sin embargo, después de revisar la API del paquete, confirmé que no hay forma de realizar esta tarea. Entonces, mi solución fue evitar usar flysystem. En mi caso, necesitaba jugar con RackSpace. Entonces, finalmente decido crear mi paquete de uso y hacer mi propio paquete de almacenamiento utilizando PHP SDK para OpenStack .

De esta manera, tiene acceso completo a las funciones que necesita getPublicUrl()para obtener la URL pública de un contenedor 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);

En conclusión, si necesita llevar el servicio de almacenamiento a otro nivel, entonces flysystemno es suficiente. Para localpropósitos, puede probar la solución de @ nXu

manix
fuente
3

Si necesita una URL absoluta del archivo, use el siguiente código:

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

Método de almacenamiento:

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

Ruta:

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

Controlador:

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

        return new Response($file, 200);
    }

Ver:

 <img src="{{ route('product.image', ['filename' => $yourImageName]) }}" alt="your image"/>
MevlütÖzdemir
fuente
¿Por qué alguien haría eso, por qué usar s3 y luego broxy en el servidor web?
Shady Keshk
2

Otra solución que encontré es esta:

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

Devolverá la URL con la ruta base del almacenamiento de documentos

Marc García
fuente
1

Eche un vistazo a esto: Cómo usar storage_path () para ver una imagen en laravel 4 . Lo mismo se aplica a Laravel 5:

El almacenamiento es para el sistema de archivos y el servidor web no puede acceder a la mayor parte de él. La solución recomendada es almacenar las imágenes en algún lugar de la carpeta pública (que es la raíz del documento), public/screenshots/por ejemplo. Luego, cuando desee mostrarlos, utilice asset('screenshots/1.jpg').

nXu
fuente
Estoy tratando de configurar un 'disco' para que sea mi carpeta pública al desarrollar y s3 ​​cuando
esté
Realmente no importa, Storage::path()devuelve la ruta del archivo en su servidor, pero necesita una URL y el servidor web solo puede servir archivos desde la raíz de su documento, que es <project>/public. Crea tus directorios dentro de él y usaurl() o asset()en las plantillas blade.
nXu
2
Storage::path()no existe, aunque me gustaría que
hiciera daviestar
Está bien, lo he entendido mal, lo siento. Lo que haría, sigue siendo lo mismo: guardar la ruta completa a la base de datos, ya sea local o s3. Al cargar / crear imágenes, simplemente verifique getenv('debug')y decida cuál usar.
nXu
Estaba tratando de evitar guardar la ruta completa, pero tal vez sea la forma más sensata de hacerlo.
daviestar
1

En mi caso, hice un método separado para archivos locales, en este archivo: 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');
    }
}

luego, creo una solicitud de extracción al marco, pero aún no se ha fusionado con el núcleo principal: https://github.com/laravel/framework/pull/13605 Puede que alguien fusione este))

Ruslan Terekhov
fuente
0

este trabajo para mí en 2020 en laravel 7

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

para que puedas usarlo así

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