1. Profundizando
  2. Almacenamiento de archivos

Introducción

Laravel proporciona una potente abstracción del sistema de archivos gracias al maravilloso paquete PHP Flysystem de Frank de Jonge. La integración de Laravel con Flysystem proporciona controladores simples para trabajar con sistemas de archivos locales, SFTP y Amazon S3. Aún mejor, es sorprendentemente sencillo cambiar entre estas opciones de almacenamiento entre tu máquina de desarrollo local y el servidor de producción, ya que la API sigue siendo la misma para cada sistema.

Configuración

El archivo de configuración del sistema de archivos de Laravel se encuentra en config/filesystems.php. Dentro de este archivo, puedes configurar todos tus "discos" de sistema de archivos. Cada disco representa un controlador de almacenamiento y una ubicación de almacenamiento específica. En el archivo de configuración se incluyen configuraciones de ejemplo para cada controlador admitido, para que puedas modificar la configuración según tus preferencias de almacenamiento y credenciales.

El controlador local interactúa con archivos almacenados localmente en el servidor que ejecuta la aplicación Laravel, mientras que el controlador s3 se utiliza para escribir en el servicio de almacenamiento en la nube Amazon S3.

Nota Puedes configurar tantos discos como desees y incluso tener varios discos que utilicen el mismo controlador.

Controlador Local

Al usar el controlador local, todas las operaciones de archivo son relativas al directorio root definido en tu archivo de configuración filesystems. De forma predeterminada, este valor está configurado en el directorio storage/app. Por lo tanto, el siguiente método escribiría en storage/app/example.txt:

use Illuminate\Support\Facades\Storage;
 
Storage::disk('local')->put('example.txt', 'Contents');

Disco Público

El disco public incluido en el archivo de configuración filesystems de tu aplicación está destinado a archivos que van a ser públicamente accesibles. De forma predeterminada, el disco public utiliza el controlador local y almacena sus archivos en storage/app/public.

Para que estos archivos sean accesibles desde la web, debes crear un enlace simbólico desde public/storage hasta storage/app/public. Utilizar esta convención de carpetas mantendrá tus archivos públicamente accesibles en un directorio que se puede compartir fácilmente entre implementaciones cuando se utilizan sistemas de implementación sin tiempo de inactividad como Envoyer.

Para crear el enlace simbólico, puedes usar el comando Artisan storage:link:

php artisan storage:link

Una vez que se ha almacenado un archivo y se ha creado el enlace simbólico, puedes crear una URL a los archivos utilizando el ayudante asset:

echo asset('storage/file.txt');

Puedes configurar enlaces simbólicos adicionales en tu archivo de configuración filesystems. Cada uno de los enlaces configurados se creará cuando ejecutes el comando storage:link:

'links' => [
public_path('storage') => storage_path('app/public'),
public_path('images') => storage_path('app/images'),
],

Requisitos Previos del Controlador

Configuración del Controlador S3

Antes de usar el controlador S3, deberás instalar el paquete Flysystem S3 mediante el administrador de paquetes Composer:

composer require league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies

La información de configuración del controlador S3 se encuentra en tu archivo de configuración config/filesystems.php. Este archivo contiene un array de configuración de ejemplo para un controlador S3. Puedes modificar este array con tu propia configuración y credenciales de S3. Por conveniencia, estas variables de entorno coinciden con la convención de nombres utilizada por AWS CLI.

Configuración del Controlador FTP

Antes de usar el controlador FTP, deberás instalar el paquete Flysystem FTP mediante el administrador de paquetes Composer:

composer require league/flysystem-ftp "^3.0"

Las integraciones de Flysystem de Laravel funcionan muy bien con FTP; sin embargo, no se incluye una configuración de ejemplo con el archivo de configuración filesystems.php predeterminado del framework. Si necesitas configurar un sistema de archivos FTP, puedes utilizar el ejemplo de configuración a continuación:

'ftp' => [
'driver' => 'ftp',
'host' => env('FTP_HOST'),
'username' => env('FTP_USERNAME'),
'password' => env('FTP_PASSWORD'),
 
// Configuración opcional de FTP...
// 'port' => env('FTP_PORT', 21),
// 'root' => env('FTP_ROOT'),
// 'passive' => true,
// 'ssl' => true,
// 'timeout' => 30,
],

Configuración del Controlador SFTP

Antes de usar el controlador SFTP, deberás instalar el paquete Flysystem SFTP mediante el administrador de paquetes Composer:

composer require league/flysystem-sftp-v3 "^3.0"

Las integraciones de Flysystem de Laravel funcionan muy bien con SFTP; sin embargo, no se incluye una configuración de ejemplo en el archivo de configuración predeterminado filesystems.php del framework. Si necesitas configurar un sistema de archivos SFTP, puedes utilizar el ejemplo de configuración a continuación:

'sftp' => [
'driver' => 'sftp',
'host' => env('SFTP_HOST'),
 
// Configuración para autenticación básica...
'username' => env('SFTP_USERNAME'),
'password' => env('SFTP_PASSWORD'),
 
// Configuración para autenticación basada en clave SSH con contraseña de encriptación...
'privateKey' => env('SFTP_PRIVATE_KEY'),
'passphrase' => env('SFTP_PASSPHRASE'),
 
// Configuración para permisos de archivos/directorios...
'visibility' => 'private', // `private` = 0600, `public` = 0644
'directory_visibility' => 'private', // `private` = 0700, `public` = 0755
 
// Configuración opcional de SFTP...
// 'hostFingerprint' => env('SFTP_HOST_FINGERPRINT'),
// 'maxTries' => 4,
// 'passphrase' => env('SFTP_PASSPHRASE'),
// 'port' => env('SFTP_PORT', 22),
// 'root' => env('SFTP_ROOT', ''),
// 'timeout' => 30,
// 'useAgent' => true,
],

Sistemas de Archivos con Ámbito y Solo Lectura

Los discos con ámbito te permiten definir un sistema de archivos donde todos los caminos se prefijan automáticamente con un prefijo de camino dado. Antes de crear un disco de sistema de archivos con ámbito, deberás instalar un paquete adicional de Flysystem mediante el administrador de paquetes Composer:

composer require league/flysystem-path-prefixing "^3.0"

Puedes crear una instancia con ámbito de camino de cualquier disco de sistema de archivos existente definiendo un disco que utilice el controlador scoped. Por ejemplo, puedes crear un disco que limite tu disco s3 existente a un prefijo de camino específico, y luego cada operación de archivo utilizando tu disco con ámbito utilizará el prefijo especificado:

's3-videos' => [
'driver' => 'scoped',
'disk' => 's3',
'prefix' => 'path/to/videos',
],

Los discos "solo lectura" te permiten crear discos de sistema de archivos que no permiten operaciones de escritura. Antes de usar la opción de configuración read-only, deberás instalar un paquete adicional de Flysystem mediante el administrador de paquetes Composer:

composer require league/flysystem-read-only "^3.0"

A continuación, puedes incluir la opción de configuración read-only en uno o más de los arrays de configuración de tus discos:

's3-videos' => [
'driver' => 's3',
// ...
'read-only' => true,
],

Sistemas de Archivos Compatibles con Amazon S3

Por defecto, el archivo de configuración filesystems de tu aplicación contiene una configuración de disco para el disco s3. Además de usar este disco para interactuar con Amazon S3, puedes usarlo para interactuar con cualquier servicio de almacenamiento de archivos compatible con S3, como MinIO o DigitalOcean Spaces.

Por lo general, después de actualizar las credenciales del disco para que coincidan con las credenciales del servicio que planeas usar, solo necesitas actualizar el valor de la opción de configuración endpoint. El valor de esta opción se define típicamente mediante la variable de entorno AWS_ENDPOINT:

'endpoint' => env('AWS_ENDPOINT', 'https://minio:9000'),

MinIO

Para que la integración de Flysystem de Laravel genere URL adecuadas al usar MinIO, debes definir la variable de entorno AWS_URL de modo que coincida con la URL local de tu aplicación e incluya el nombre del bucket en la ruta de la URL:

AWS_URL=http://localhost:9000/local

Advertencia No se admite la generación de URL de almacenamiento temporal mediante el método temporaryUrl al usar MinIO.

Obtención de Instancias de Disco

La fachada Storage se puede utilizar para interactuar con cualquiera de tus discos configurados. Por ejemplo, puedes usar el método put en la fachada para almacenar un avatar en el disco predeterminado. Si llamas a métodos en la fachada Storage sin llamar primero al método disk, el método se pasará automáticamente al disco predeterminado:

use Illuminate\Support\Facades\Storage;
 
Storage::put('avatars/1', $content);

Si tu aplicación interactúa con varios discos, puedes usar el método disk en la fachada Storage para trabajar con archivos en un disco específico:

Storage::disk('s3')->put('avatars/1', $content);

Discos Bajo Demanda

A veces, es posible que desees crear un disco en tiempo de ejecución utilizando una configuración dada sin que esa configuración esté presente en el archivo de configuración filesystems de tu aplicación. Para lograr esto, puedes pasar un array de configuración al método build de la fachada Storage:

use Illuminate\Support\Facades\Storage;
 
$disk = Storage::build([
'driver' => 'local',
'root' => '/path/to/root',
]);
 
$disk->put('image.jpg', $content);

Recuperación de Archivos

El método get se puede utilizar para recuperar el contenido de un archivo. El método devolverá el contenido de cadena sin procesar del archivo. Recuerda que todos los caminos de archivo deben especificarse en relación con la "raíz" del disco:

$contents = Storage::get('file.jpg');

Si el archivo que estás recuperando contiene JSON, puedes utilizar el método json para recuperar el archivo y decodificar su contenido:

$orders = Storage::json('orders.json');

El método exists se puede utilizar para determinar si un archivo existe en el disco:

if (Storage::disk('s3')->exists('file.jpg')) {
// ...
}

El método missing se puede utilizar para determinar si un archivo falta en el disco:

if (Storage::disk('s3')->missing('file.jpg')) {
// ...
}

Descarga de Archivos

El método download se puede utilizar para generar una respuesta que obliga al navegador del usuario a descargar el archivo en la ruta especificada. El método download acepta un nombre de archivo como segundo argumento al método, que determinará el nombre de archivo que verá el usuario que descargue el archivo. Finalmente, puedes pasar un array de encabezados HTTP como tercer argumento al método:

return Storage::download('file.jpg');
 
return Storage::download('file.jpg', $name, $headers);

URLs de Archivos

Puedes usar el método url para obtener la URL de un archivo dado. Si estás utilizando el controlador local, esto simplemente agregará /storage al camino dado y devolverá una URL relativa al archivo. Si estás utilizando el controlador s3, se devolverá la URL remota completamente calificada:

use Illuminate\Support\Facades\Storage;
 
$url = Storage::url('file.jpg');

Al usar el controlador local, todos los archivos que deben ser accesibles públicamente deben colocarse en el directorio storage/app/public. Además, debes crear un enlace simbólico en public/storage que apunte al directorio storage/app/public.

Advertencia Al usar el controlador local, el valor de retorno de url no está codificado en URL. Por esta razón, recomendamos almacenar siempre tus archivos con nombres que generen URL válidas.

Personalización del Host de URL

Si deseas predefinir el host para las URL generadas mediante la fachada Storage, puedes agregar una opción url al array de configuración del disco:

'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],

URLs Temporales

Utilizando el método temporaryUrl, puedes crear URL temporales para archivos almacenados con el controlador s3. Este método acepta un camino y una instancia de DateTime especificando cuándo debería caducar la URL:

use Illuminate\Support\Facades\Storage;
 
$url = Storage::temporaryUrl(
'file.jpg', now()->addMinutes(5)
);

Si necesitas especificar parámetros adicionales de solicitud de S3, puedes pasar el array de parámetros de solicitud como tercer argumento al método temporaryUrl:

$url = Storage::temporaryUrl(
'file.jpg',
now()->addMinutes(5),
[
'ResponseContentType' => 'application/octet-stream',
'ResponseContentDisposition' => 'attachment; filename=file2.jpg',
]
);

Si necesitas personalizar cómo se crean las URL temporales para un disco de almacenamiento específico, puedes utilizar el método buildTemporaryUrlsUsing. Por ejemplo, esto puede ser útil si tienes un controlador que te permite descargar archivos almacenados a través de un disco que normalmente no admite URL temporales. Por lo general, este método debe llamarse desde el método boot de un proveedor de servicios:

<?php
 
namespace App\Providers;
 
use DateTime;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
 
class AppServiceProvider extends ServiceProvider
{
/**
* Inicializa cualquier servicio de la aplicación.
*/
public function boot(): void
{
Storage::disk('local')->buildTemporaryUrlsUsing(
function (string $path, DateTime $expiration, array $options) {
return URL::temporarySignedRoute(
'files.download',
$expiration,
array_merge($options, ['path' => $path])
);
}
);
}
}

URLs Temporales de Carga

Advertencia La capacidad de generar URL temporales de carga solo es compatible con el controlador s3.

Si necesitas generar una URL temporal que se pueda utilizar para cargar un archivo directamente desde tu aplicación del lado del cliente, puedes utilizar el método temporaryUploadUrl. Este método acepta una ruta y una instancia de DateTime que especifica cuándo debería caducar la URL. El método temporaryUploadUrl devuelve un array asociativo que se puede desestructurar en la URL de carga y los encabezados que deben incluirse con la solicitud de carga:

use Illuminate\Support\Facades\Storage;
 
['url' => $url, 'headers' => $headers] = Storage::temporaryUploadUrl(
'file.jpg', now()->addMinutes(5)
);

Este método es útil principalmente en entornos sin servidor que requieren que la aplicación del lado del cliente cargue directamente archivos a un sistema de almacenamiento en la nube como Amazon S3.

Metadatos de Archivos

Además de leer y escribir archivos, Laravel también puede proporcionar información sobre los propios archivos. Por ejemplo, el método size se puede utilizar para obtener el tamaño de un archivo en bytes:

use Illuminate\Support\Facades\Storage;
 
$size = Storage::size('file.jpg');

El método lastModified devuelve la marca de tiempo UNIX de la última vez que se modificó el archivo:

$time = Storage::lastModified('file.jpg');

El tipo MIME de un archivo dado se puede obtener mediante el método mimeType:

$mime = Storage::mimeType('file.jpg');

Rutas de Archivos

Puedes usar el método path para obtener la ruta de un archivo dado. Si estás utilizando el controlador local, esto devolverá la ruta absoluta al archivo. Si estás utilizando el controlador s3, este método devolverá la ruta relativa al archivo en el bucket de S3:

use Illuminate\Support\Facades\Storage;
 
$path = Storage::path('file.jpg');

Almacenamiento de Archivos

El método put se puede utilizar para almacenar el contenido de un archivo en un disco. También puedes pasar un recurso PHP al método put, que utilizará el soporte de transmisión subyacente de Flysystem. Recuerda que todos los caminos de archivo deben especificarse en relación con la ubicación "raíz" configurada para el disco:

use Illuminate\Support\Facades\Storage;
 
Storage::put('file.jpg', $contents);
 
Storage::put('file.jpg', $resource);

Escrituras Fallidas

Si el método put (u otras operaciones de "escritura") no puede escribir el archivo en el disco, se devolverá false:

if (! Storage::put('file.jpg', $contents)) {
// El archivo no se pudo escribir en el disco...
}

Si lo deseas, puedes definir la opción throw dentro del array de configuración del disco de tu sistema de archivos. Cuando esta opción se define como true, los métodos de "escritura" como put lanzarán una instancia de League\Flysystem\UnableToWriteFile cuando las operaciones de escritura fallen:

'public' => [
'driver' => 'local',
// ...
'throw' => true,
],

Agregar al Principio y al Final de los Archivos

Los métodos prepend y append te permiten escribir al principio o al final de un archivo:

Storage::prepend('file.log', 'Prepended Text');
 
Storage::append('file.log', 'Appended Text');

Copiar y Mover Archivos

El método copy se puede utilizar para copiar un archivo existente a una nueva ubicación en el disco, mientras que el método move se puede utilizar para cambiar el nombre o mover un archivo existente a una nueva ubicación:

Storage::copy('old/file.jpg', 'new/file.jpg');
 
Storage::move('old/file.jpg', 'new/file.jpg');

Transmisión Automática

La transmisión de archivos al almacenamiento ofrece un uso significativamente reducido de la memoria. Si deseas que Laravel gestione automáticamente la transmisión de un archivo determinado a tu ubicación de almacenamiento, puedes utilizar los métodos putFile o putFileAs. Este método acepta una instancia de Illuminate\Http\File o Illuminate\Http\UploadedFile y transmitirá automáticamente el archivo a la ubicación deseada:

use Illuminate\Http\File;
use Illuminate\Support\Facades\Storage;
 
// Generar automáticamente un ID único para el nombre de archivo...
$path = Storage::putFile('photos', new File('/path/to/photo'));
 
// Especificar manualmente un nombre de archivo...
$path = Storage::putFileAs('photos', new File('/path/to/photo'), 'photo.jpg');

Hay algunas cosas importantes que debes tener en cuenta sobre el método putFile. Ten en cuenta que solo especificamos un nombre de directorio y no un nombre de archivo. De forma predeterminada, el método putFile generará un ID único para servir como nombre de archivo. La extensión del archivo se determinará examinando el tipo MIME del archivo. La ruta al archivo será devuelta por el método putFile para que puedas almacenar la ruta, incluido el nombre de archivo generado, en tu base de datos.

Los métodos putFile y putFileAs también aceptan un argumento para especificar la "visibilidad" del archivo almacenado. Esto es particularmente útil si estás almacenando el archivo en un disco en la nube como Amazon S3 y deseas que el archivo sea accesible públicamente a través de las URL generadas:

Storage::putFile('photos', new File('/path/to/photo'), 'public');

Subida de Archivos

En las aplicaciones web, uno de los casos de uso más comunes para almacenar archivos es almacenar archivos cargados por el usuario, como fotos y documentos. Laravel facilita mucho el almacenamiento de archivos cargados usando el método store en una instancia de archivo cargado. Llama al método store con la ruta en la que deseas almacenar el archivo cargado:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
 
class UserAvatarController extends Controller
{
/**
* Actualiza el avatar del usuario.
*/
public function update(Request $request): string
{
$path = $request->file('avatar')->store('avatars');
 
return $path;
}
}

Hay algunas cosas importantes que debes tener en cuenta sobre este ejemplo. Ten en cuenta que solo especificamos un nombre de directorio, no un nombre de archivo. De forma predeterminada, el método store generará un ID único para servir como nombre de archivo. La extensión del archivo se determinará examinando el tipo MIME del archivo. La ruta al archivo será devuelta por el método store para que puedas almacenar la ruta, incluido el nombre de archivo generado, en tu base de datos.

También puedes llamar al método putFile en la fachada Storage para realizar la misma operación de almacenamiento de archivos que el ejemplo anterior:

$path = Storage::putFile('avatars', $request->file('avatar'));

Especificación de un Nombre de Archivo

Si no quieres que se asigne automáticamente un nombre de archivo a tu archivo almacenado, puedes usar el método storeAs, que recibe la ruta, el nombre de archivo y (opcionalmente) el disco como argumentos:

$path = $request->file('avatar')->storeAs(
'avatars', $request->user()->id
);

También puedes usar el método putFileAs en la fachada Storage, que realizará la misma operación de almacenamiento de archivos que el ejemplo anterior:

$path = Storage::putFileAs(
'avatars', $request->file('avatar'), $request->user()->id
);

Advertencia Los caracteres unicode no imprimibles e inválidos se eliminarán automáticamente de los nombres de archivo. Por lo tanto, es posible que desees sanear tus rutas de archivo antes de pasarlas a los métodos de almacenamiento de archivos de Laravel. Las rutas de archivo se normalizan mediante el método League\Flysystem\WhitespacePathNormalizer::normalizePath.

Especificación de un Disco

De forma predeterminada, el método store de este archivo cargado utilizará tu disco predeterminado. Si deseas especificar otro disco, pasa el nombre del disco como segundo argumento al método store:

$path = $request->file('avatar')->store(
'avatars/'.$request->user()->id, 's3'
);

Si estás utilizando el método storeAs, puedes pasar el nombre del disco como tercer argumento al método:

$path = $request->file('avatar')->storeAs(
'avatars',
$request->user()->id,
's3'
);

Otra Información sobre Archivos Cargados

Si deseas obtener el nombre y la extensión originales del archivo cargado, puedes hacerlo utilizando los métodos getClientOriginalName y getClientOriginalExtension:

$file = $request->file('avatar');
 
$name = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();

Sin embargo, ten en cuenta que los métodos getClientOriginalName y getClientOriginalExtension se consideran inseguros, ya que el nombre del archivo y la extensión pueden ser manipulados por un usuario malicioso. Por esta razón, generalmente se prefiere utilizar los métodos hashName y extension para obtener un nombre y una extensión para el archivo cargado:

$file = $request->file('avatar');
 
$name = $file->hashName(); // Generate a unique, random name...
$extension = $file->extension(); // Determine the file's extension based on the file's MIME type...

Visibilidad de Archivos

En la integración de Flysystem de Laravel, la "visibilidad" es una abstracción de los permisos de archivo en varias plataformas. Los archivos pueden declararse como public o private. Cuando se declara un archivo como public, estás indicando que el archivo debería ser accesible para otros en general. Por ejemplo, al usar el controlador S3, puedes recuperar URL para archivos public.

Puedes establecer la visibilidad al escribir el archivo mediante el método put:

use Illuminate\Support\Facades\Storage;
 
Storage::put('file.jpg', $contents, 'public');

Si el archivo ya ha sido almacenado, su visibilidad se puede recuperar y establecer mediante los métodos getVisibility y setVisibility:

$visibility = Storage::getVisibility('file.jpg');
 
Storage::setVisibility('file.jpg', 'public');

Al interactuar con archivos cargados, puedes utilizar los métodos storePublicly y storePubliclyAs para almacenar el archivo cargado con visibilidad public:

$path = $request->file('avatar')->storePublicly('avatars', 's3');
 
$path = $request->file('avatar')->storePubliclyAs(
'avatars',
$request->user()->id,
's3'
);

Archivos Locales y Visibilidad

Cuando usas el controlador local, la visibilidad public se traduce en permisos 0755 para directorios y permisos 0644 para archivos. Puedes modificar las asignaciones de permisos en el archivo de configuración filesystems de tu aplicación:

'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'permissions' => [
'file' => [
'public' => 0644,
'private' => 0600,
],
'dir' => [
'public' => 0755,
'private' => 0700,
],
],
],

Eliminación de Archivos

El método delete acepta un solo nombre de archivo o un array de archivos para eliminar:

use Illuminate\Support\Facades\Storage;
 
Storage::delete('file.jpg');
 
Storage::delete(['file.jpg', 'file2.jpg']);

Si es necesario, puedes especificar el disco del cual se debe eliminar el archivo:

use Illuminate\Support\Facades\Storage;
 
Storage::disk('s3')->delete('path/file.jpg');

Directorios

Obtener Todos los Archivos Dentro de un Directorio

El método files devuelve un array de todos los archivos en un directorio dado. Si deseas obtener una lista de todos los archivos dentro de un directorio dado, incluidos todos los subdirectorios, puedes usar el método allFiles:

use Illuminate\Support\Facades\Storage;
 
$files = Storage::files($directory);
 
$files = Storage::allFiles($directory);

Obtener Todos los Directorios Dentro de un Directorio

El método directories devuelve un array de todos los directorios dentro de un directorio dado. Además, puedes usar el método allDirectories para obtener una lista de todos los directorios dentro de un directorio dado y todos sus subdirectorios:

$directories = Storage::directories($directory);
 
$directories = Storage::allDirectories($directory);

Crear un Directorio

El método makeDirectory creará el directorio dado, incluidos los subdirectorios necesarios:

Storage::makeDirectory($directory);

Eliminar un Directorio

Finalmente, el método deleteDirectory se puede utilizar para eliminar un directorio y todos sus archivos:

Storage::deleteDirectory($directory);

Pruebas

El método fake de la fachada Storage te permite generar fácilmente un disco falso que, combinado con las utilidades de generación de archivos de la clase Illuminate\Http\UploadedFile, simplifica enormemente las pruebas de carga de archivos. Por ejemplo:

<?php
 
namespace Tests\Feature;
 
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
 
class ExampleTest extends TestCase
{
public function test_albums_can_be_uploaded(): void
{
Storage::fake('photos');
 
$response = $this->json('POST', '/photos', [
UploadedFile::fake()->image('photo1.jpg'),
UploadedFile::fake()->image('photo2.jpg')
]);
 
// Asegura que se hayan almacenado uno o más archivos...
Storage::disk('photos')->assertExists('photo1.jpg');
Storage::disk('photos')->assertExists(['photo1.jpg', 'photo2.jpg']);
 
// Asegura que uno o más archivos no se hayan almacenado...
Storage::disk('photos')->assertMissing('missing.jpg');
Storage::disk('photos')->assertMissing(['missing.jpg', 'non-existing.jpg']);
 
// Asegura que un directorio dado esté vacío...
Storage::disk('photos')->assertDirectoryEmpty('/wallpapers');
}
}

De forma predeterminada, el método fake eliminará todos los archivos en su directorio temporal. Si deseas conservar estos archivos, puedes usar el método "persistentFake" en su lugar. Para obtener más información sobre las pruebas de carga de archivos, puedes consultar la documentación de pruebas HTTP sobre cargas de archivos.

Advertencia El método image requiere la extensión GD.

Sistemas de Archivos Personalizados

La integración de Flysystem de Laravel proporciona soporte para varios "controladores" fuera de la caja; sin embargo, Flysystem no se limita a estos y tiene adaptadores para muchos otros sistemas de almacenamiento. Puedes crear un controlador personalizado si deseas utilizar uno de estos adaptadores adicionales en tu aplicación Laravel.

Para definir un sistema de archivos personalizado, necesitarás un adaptador de Flysystem. Agreguemos un adaptador de Dropbox mantenido por la comunidad a nuestro proyecto:

composer require spatie/flysystem-dropbox

A continuación, puedes registrar el controlador dentro del método boot de uno de los proveedores de servicios de tu aplicación. Para hacer esto, debes usar el método extend de la fachada Storage:

<?php
 
namespace App\Providers;
 
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\ServiceProvider;
use League\Flysystem\Filesystem;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;
 
class AppServiceProvider extends ServiceProvider
{
/**
* Registra cualquier servicio de la aplicación.
*/
public function register(): void
{
// ...
}
 
/**
* Inicializa cualquier servicio de la aplicación.
*/
public function boot(): void
{
Storage::extend('dropbox', function (Application $app, array $config) {
$adapter = new DropboxAdapter(new DropboxClient(
$config['authorization_token']
));
 
return new FilesystemAdapter(
new Filesystem($adapter, $config),
$adapter,
$config
);
});
}
}

El primer argumento del método extend es el nombre del controlador y el segundo es un cierre que recibe las variables $app y $config. El cierre debe devolver una instancia de Illuminate\Filesystem\FilesystemAdapter. La variable $config contiene los valores definidos en config/filesystems.php para el disco especificado.

Una vez que hayas creado y registrado el proveedor de servicios de la extensión, puedes usar el controlador dropbox en tu archivo de configuración config/filesystems.php.