> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Stockage de fichiers

> Lire, écrire, uploader des fichiers et intégrer un stockage cloud grâce à l'intégration Flysystem de Laravel.

## Qu'est-ce que le stockage de fichiers

Laravel fournit une couche d'abstraction puissante basée sur le package PHP [Flysystem](https://github.com/thephpleague/flysystem).
Vous manipulez disque local, SFTP, Amazon S3, etc. avec la même API — **sans changer de code** en basculant de backend.

<Info>
  Changer de driver ne change pas votre code. Vous pouvez utiliser le disque local en dev et S3 en production sans effort.
</Info>

## Configuration

La configuration se trouve dans `config/filesystems.php` où vous définissez des « disques » (combinaison driver + emplacement).

Principaux drivers :

| Driver   | Usage                                |
| -------- | ------------------------------------ |
| `local`  | Système de fichiers local du serveur |
| `public` | Disque local pour fichiers publics   |
| `s3`     | Amazon S3 (ou compatible)            |
| `sftp`   | Serveur SFTP                         |
| `ftp`    | Serveur FTP                          |

### Driver `local`

Les opérations se font relativement au `root` configuré. Par défaut : `storage/app/private`.

```php theme={null}
use Illuminate\Support\Facades\Storage;

Storage::disk('local')->put('example.txt', 'Contents');
// Écrit dans storage/app/private/example.txt
```

### Changer le disque par défaut

Variable `FILESYSTEM_DISK` :

```ini theme={null}
FILESYSTEM_DISK=s3
```

## Disque public et lien symbolique

Le disque `public` héberge les fichiers accessibles depuis le web.
Par défaut, il stocke dans `storage/app/public`.

Pour rendre accessible depuis le serveur web, créez un lien symbolique de `public/storage` vers `storage/app/public`.

<Steps>
  <Step title="Créer le lien symbolique">
    ```shell theme={null}
    php artisan storage:link
    ```
  </Step>

  <Step title="Générer l'URL du fichier">
    Après création du lien, utilisez `asset`.

    ```php theme={null}
    echo asset('storage/file.txt');
    ```
  </Step>
</Steps>

<Tip>
  Pour ajouter d'autres liens, configurez `links` dans `config/filesystems.php`.

  ```php theme={null}
  'links' => [
      public_path('storage') => storage_path('app/public'),
      public_path('images') => storage_path('app/images'),
  ],
  ```
</Tip>

Pour supprimer les liens : `storage:unlink`.

```shell theme={null}
php artisan storage:unlink
```

## Opérations avec la façade Storage

### Lecture

```php theme={null}
use Illuminate\Support\Facades\Storage;

// Contenu en chaîne
$contents = Storage::get('file.jpg');

// JSON décodé
$data = Storage::json('orders.json');

// Existence
if (Storage::exists('file.jpg')) {
    // ...
}

// Non existence
if (Storage::missing('file.jpg')) {
    // ...
}
```

### Écriture

```php theme={null}
// Écriture
Storage::put('file.jpg', $contents);

// Écriture d'un flux
Storage::put('file.jpg', $resource);

// Ajouter au début / à la fin
Storage::prepend('file.log', 'Prepended Text');
Storage::append('file.log', 'Appended Text');

// Copie / déplacement
Storage::copy('old/file.jpg', 'new/file.jpg');
Storage::move('old/file.jpg', 'new/file.jpg');
```

<Info>
  En cas d'échec, `put` retourne `false` par défaut. Configurez `'throw' => true` sur le disque pour lever une exception.
</Info>

### Suppression

```php theme={null}
Storage::delete('file.jpg');

Storage::delete(['file.jpg', 'file2.jpg']);

Storage::disk('s3')->delete('path/file.jpg');
```

### Réponse de téléchargement

```php theme={null}
return Storage::download('file.jpg');

return Storage::download('file.jpg', 'my-file.jpg', $headers);
```

## Génération d'URL

### URL normale

```php theme={null}
use Illuminate\Support\Facades\Storage;

$url = Storage::url('file.jpg');
```

`local` retourne une URL relative (`/storage/file.jpg`), `s3` retourne l'URL distante complète.

### URL temporaire

`temporaryUrl` génère une URL à durée limitée. Disponible sur `local` et `s3`.

```php theme={null}
use Illuminate\Support\Facades\Storage;

$url = Storage::temporaryUrl(
    'file.jpg',
    now()->plus(minutes: 5)
);
```

Pour S3, des paramètres supplémentaires sont possibles.

```php theme={null}
$url = Storage::temporaryUrl(
    'file.jpg',
    now()->plus(minutes: 5),
    [
        'ResponseContentType' => 'application/octet-stream',
        'ResponseContentDisposition' => 'attachment; filename=file.jpg',
    ]
);
```

<Tip>
  Pour des URLs d'upload temporaires : `temporaryUploadUrl`. Utile en architecture serverless (upload direct client → S3).

  ```php theme={null}
  ['url' => $url, 'headers' => $headers] = Storage::temporaryUploadUrl(
      'file.jpg', now()->plus(minutes: 5)
  );
  ```
</Tip>

## Upload de fichiers

### `store` (nom généré)

```php theme={null}
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserAvatarController extends Controller
{
    public function update(Request $request): string
    {
        // Nom généré depuis le type MIME
        $path = $request->file('avatar')->store('avatars');

        return $path;
    }
}
```

### `storeAs` (nom explicite)

```php theme={null}
$path = $request->file('avatar')->storeAs(
    'avatars',
    $request->user()->id
);
```

### Spécifier un disque

```php theme={null}
$path = $request->file('avatar')->store(
    'avatars/' . $request->user()->id,
    's3'
);
```

### Via la façade Storage

```php theme={null}
use Illuminate\Support\Facades\Storage;

// Nom généré
$path = Storage::putFile('avatars', $request->file('avatar'));

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

<Warning>
  `getClientOriginalName()` et `getClientOriginalExtension()` peuvent être manipulés par l'utilisateur.
  Utilisez `hashName()` et `extension()`.

  ```php theme={null}
  $file = $request->file('avatar');

  $name = $file->hashName();
  $extension = $file->extension();
  ```
</Warning>

## Visibilité des fichiers

Flysystem gère la visibilité (public / privé).

```php theme={null}
use Illuminate\Support\Facades\Storage;

Storage::put('file.jpg', $contents, 'public');

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

Pour rendre un fichier uploadé public : `storePublicly`.

```php theme={null}
$path = $request->file('avatar')->storePublicly('avatars', 's3');
```

## Utiliser plusieurs disques

```php theme={null}
Storage::put('avatars/1', $content);

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

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

## Configuration S3

### Installer le package

```shell theme={null}
composer require league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies
```

### Variables d'environnement

```ini theme={null}
AWS_ACCESS_KEY_ID=your-key-id
AWS_SECRET_ACCESS_KEY=your-secret-access-key
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=your-bucket-name
AWS_USE_PATH_STYLE_ENDPOINT=false
```

<Info>
  DigitalOcean Spaces, Cloudflare R2, Vultr Object Storage… sont accessibles via le driver `s3` en configurant `endpoint`.

  ```php theme={null}
  'endpoint' => env('AWS_ENDPOINT', 'https://your-endpoint.example.com'),
  ```
</Info>

## Métadonnées

```php theme={null}
use Illuminate\Support\Facades\Storage;

// Taille (octets)
$size = Storage::size('file.jpg');

// Dernier modif (timestamp)
$time = Storage::lastModified('file.jpg');

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

// Chemin absolu (driver local)
$path = Storage::path('file.jpg');
```

## Opérations sur les répertoires

```php theme={null}
use Illuminate\Support\Facades\Storage;

$files = Storage::files($directory);

$files = Storage::allFiles($directory);

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

Storage::makeDirectory($directory);

Storage::deleteDirectory($directory);
```

## Tests

`Storage::fake()` permet de tester sans toucher au disque réel.

```php theme={null}
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

test('avatar upload', function () {
    Storage::fake('avatars');

    $file = UploadedFile::fake()->image('avatar.jpg');

    $this->post('/user/avatar', ['avatar' => $file]);

    Storage::disk('avatars')->assertExists('avatar.jpg');

    Storage::disk('avatars')->assertMissing('other.jpg');
});
```

<Info>
  `UploadedFile::fake()->image()` nécessite l'extension [GD](https://www.php.net/manual/fr/book.image.php).
</Info>

## Exemple : upload d'avatar

Validation, sauvegarde et persistance du chemin.

```php theme={null}
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Storage;

class ProfileController extends Controller
{
    public function updateAvatar(Request $request): RedirectResponse
    {
        $request->validate([
            'avatar' => ['required', 'image', 'max:2048'],
        ]);

        $user = $request->user();

        // Supprime l'ancienne image
        if ($user->avatar_path) {
            Storage::disk('public')->delete($user->avatar_path);
        }

        // Sauvegarde la nouvelle
        $path = $request->file('avatar')->store('avatars', 'public');

        $user->update(['avatar_path' => $path]);

        return back()->with('status', 'avatar-updated');
    }
}
```

Dans le template :

```blade theme={null}
<img src="{{ Storage::disk('public')->url($user->avatar_path) }}" alt="Avatar">
```


## Related topics

- [MongoDB](/fr/mongodb.md)
- [Mise à niveau de Laravel 8 vers 9](/fr/blog/upgrade-8-to-9.md)
- [Authentification par compte de service - Google Sheets API for Laravel](/fr/packages/laravel-google-sheets/service-account.md)
- [Développement de packages Laravel](/fr/advanced/package-development.md)
- [Présentation de Laravel Wayfinder](/fr/blog/wayfinder-introduction.md)
