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

# File storage

> Come leggere e scrivere file, gestire upload e integrare storage cloud usando l'integrazione Flysystem di Laravel.

## Cos'è il file storage

Laravel fornisce un potente livello di astrazione basato sul pacchetto PHP [Flysystem](https://github.com/thephpleague/flysystem).
Disco locale, SFTP, Amazon S3 e altri backend si usano con la stessa API: puoi cambiare ambiente **senza modificare il codice**.

<Info>
  Cambiando driver, il codice resta lo stesso. In sviluppo storage locale, in produzione S3: passaggio semplice.
</Info>

## Configurazione

La configurazione è in `config/filesystems.php`, dove definisci i "disk". Un disk è la combinazione di un driver e una destinazione.

Driver principali:

| Driver   | Uso                           |
| -------- | ----------------------------- |
| `local`  | Filesystem locale del server  |
| `public` | Disco locale pubblico via web |
| `s3`     | Amazon S3 (o compatibile)     |
| `sftp`   | Server SFTP                   |
| `ftp`    | Server FTP                    |

### Driver local

Usa `root` di `filesystems`. Di default `storage/app/private`.

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

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

### Cambiare il disk predefinito

Con `FILESYSTEM_DISK`.

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

## Disk `public` e symlink

Il disk `public` è per file accessibili dal web. Di default salva in `storage/app/public`.

Per renderli raggiungibili crea il symlink `public/storage` → `storage/app/public`.

<Steps>
  <Step title="Crea il symlink">
    ```shell theme={null}
    php artisan storage:link
    ```
  </Step>

  <Step title="Ottieni l'URL del file">
    ```php theme={null}
    echo asset('storage/file.txt');
    ```
  </Step>
</Steps>

<Tip>
  Per symlink aggiuntivi configura `links` in `config/filesystems.php`.

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

Rimuovi il symlink con:

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

## Operazioni base con la facade Storage

### Lettura

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

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

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

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

### Scrittura

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

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

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

<Info>
  Se `put` fallisce restituisce `false` di default. Configura `'throw' => true` per lanciare un'eccezione.
</Info>

### Eliminazione

```php theme={null}
Storage::delete('file.jpg');
Storage::delete(['file.jpg', 'file2.jpg']);
Storage::disk('s3')->delete('path/file.jpg');
```

### Download

```php theme={null}
return Storage::download('file.jpg');
return Storage::download('file.jpg', 'my-file.jpg', $headers);
```

## URL

### URL normale

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

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

Con `local` è relativo (`/storage/file.jpg`), con `s3` è l'URL completo.

### URL temporaneo

Con `temporaryUrl` (disponibile per `local` e `s3`).

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

Su S3 puoi passare parametri aggiuntivi:

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

<Tip>
  Per URL di upload temporaneo usa `temporaryUploadUrl`. Utile per upload client-side diretto verso S3.

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

## Upload di file

### store (nome file auto)

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

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserAvatarController extends Controller
{
    public function update(Request $request): string
    {
        $path = $request->file('avatar')->store('avatars');
        return $path;
    }
}
```

### storeAs (nome specifico)

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

### Con disk specifico

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

### Via facade Storage

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

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

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

<Warning>
  `getClientOriginalName()` e `getClientOriginalExtension()` sono manipolabili dall'utente: non sicuri. Usa `hashName()` ed `extension()`.

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

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

## Visibilità

In Flysystem la visibilità pubblica/privata si gestisce con `visibility`.

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

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

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

Per salvare pubblicamente file caricati usa `storePublicly`.

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

## Più disk

```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);
```

## Storage cloud (S3)

### Installazione

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

### Variabili d'ambiente

```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>
  Anche servizi S3-compatibili (DigitalOcean Spaces, Cloudflare R2, Vultr Object Storage) usano il driver `s3`. Imposta `endpoint` con l'URL del servizio.

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

## Metadata

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

$size = Storage::size('file.jpg');
$time = Storage::lastModified('file.jpg');
$mime = Storage::mimeType('file.jpg');
$path = Storage::path('file.jpg');
```

## Directory

```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);
```

## Test

`Storage::fake()` per test senza toccare disk reali.

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

test('è possibile caricare l\'avatar', 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()` richiede l'estensione [GD](https://www.php.net/manual/en/book.image.php) di PHP.
</Info>

## Esempio pratico: upload dell'avatar

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

        if ($user->avatar_path) {
            Storage::disk('public')->delete($user->avatar_path);
        }

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

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

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

Nel template:

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


## Related topics

- [Laravel AI SDK](/it/ai-sdk.md)
- [Laravel MCP](/it/mcp.md)
- [Guida all'aggiornamento da Laravel 11 a 12](/it/blog/upgrade-11-to-12.md)
- [Struttura delle directory](/it/directory-structure.md)
- [Aggiornamento da Laravel 8 a 9](/it/blog/upgrade-8-to-9.md)
