Processing uploads on the server | laravel-medialibrary | Spatie

 SPATIE

  Laravel Media Library
========================

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Laravel-medialibrary](https://spatie.be/docs/laravel-medialibrary/v9)  Handling-uploads-with-media-library-pro  Processing uploads on the server

 Version   v11   v10   v9   v8   v7   v6   v5   v4   v3

 Other versions for crawler [v11](https://spatie.be/docs/laravel-medialibrary/v11) [v10](https://spatie.be/docs/laravel-medialibrary/v10) [v9](https://spatie.be/docs/laravel-medialibrary/v9) [v8](https://spatie.be/docs/laravel-medialibrary/v8) [v7](https://spatie.be/docs/laravel-medialibrary/v7) [v6](https://spatie.be/docs/laravel-medialibrary/v6) [v5](https://spatie.be/docs/laravel-medialibrary/v5) [v4](https://spatie.be/docs/laravel-medialibrary/v4) [v3](https://spatie.be/docs/laravel-medialibrary/v3)

- [ Introduction ](https://spatie.be/docs/laravel-medialibrary/v9/introduction)
- [ Support us ](https://spatie.be/docs/laravel-medialibrary/v9/support-us)
- [ Base installation ](https://spatie.be/docs/laravel-medialibrary/v9/installation-setup)
- [ Questions and issues ](https://spatie.be/docs/laravel-medialibrary/v9/questions-issues)
- [ Requirements ](https://spatie.be/docs/laravel-medialibrary/v9/requirements)
- [ Upgrading ](https://spatie.be/docs/laravel-medialibrary/v9/upgrading)
- [ Changelog ](https://spatie.be/docs/laravel-medialibrary/v9/changelog)
- [ Troubleshooting ](https://spatie.be/docs/laravel-medialibrary/v9/troubleshooting)
- [ About us ](https://spatie.be/docs/laravel-medialibrary/v9/about-us)

Basic usage
-----------

- [ Preparing your model ](https://spatie.be/docs/laravel-medialibrary/v9/basic-usage/preparing-your-model)
- [ Associating files ](https://spatie.be/docs/laravel-medialibrary/v9/basic-usage/associating-files)
- [ Retrieving media ](https://spatie.be/docs/laravel-medialibrary/v9/basic-usage/retrieving-media)

Working with media collections
------------------------------

- [ Simple media collections ](https://spatie.be/docs/laravel-medialibrary/v9/working-with-media-collections/simple-media-collections)
- [ Defining media collections ](https://spatie.be/docs/laravel-medialibrary/v9/working-with-media-collections/defining-media-collections)

Converting images
-----------------

- [ Defining conversions ](https://spatie.be/docs/laravel-medialibrary/v9/converting-images/defining-conversions)
- [ Retrieving converted images ](https://spatie.be/docs/laravel-medialibrary/v9/converting-images/retrieving-converted-images)
- [ Optimizing converted images ](https://spatie.be/docs/laravel-medialibrary/v9/converting-images/optimizing-converted-images)
- [ Regenerating images ](https://spatie.be/docs/laravel-medialibrary/v9/converting-images/regenerating-images)

Handling uploads with Media Library Pro
---------------------------------------

- [ Introduction ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/introduction)
- [ Installation ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/installation)
- [ Processing uploads on the server ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/processing-uploads-on-the-server)
- [ Handling uploads with Blade ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/handling-uploads-with-blade)
- [ Handling uploads with Livewire ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/handling-uploads-with-livewire)
- [ Handling uploads with Vue ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/handling-uploads-with-vue)
- [ Handling uploads with React ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/handling-uploads-with-react)
- [ Creating custom Vue components ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/creating-custom-vue-components)
- [ Creating custom React components ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/creating-custom-react-components)
- [ Customizing CSS ](https://spatie.be/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/customizing-css)

Responsive images
-----------------

- [ Getting started with responsive images ](https://spatie.be/docs/laravel-medialibrary/v9/responsive-images/getting-started-with-responsive-images)
- [ Using your own width calculator ](https://spatie.be/docs/laravel-medialibrary/v9/responsive-images/using-your-own-width-calculator)
- [ Customizing the rendered html ](https://spatie.be/docs/laravel-medialibrary/v9/responsive-images/customizing-the-rendered-html)
- [ Generating your own tiny placeholder ](https://spatie.be/docs/laravel-medialibrary/v9/responsive-images/generating-your-own-tiny-placeholder)
- [ Responsive images demo ](https://spatie.be/docs/laravel-medialibrary/v9/responsive-images/demo)

Converting other file types
---------------------------

- [ Using image generators ](https://spatie.be/docs/laravel-medialibrary/v9/converting-other-file-types/using-image-generators)
- [ Creating a custom image generator ](https://spatie.be/docs/laravel-medialibrary/v9/converting-other-file-types/creating-a-custom-image-generator)

Downloading media
-----------------

- [ Downloading a single file ](https://spatie.be/docs/laravel-medialibrary/v9/downloading-media/downloading-a-single-file)
- [ Downloading multiple files ](https://spatie.be/docs/laravel-medialibrary/v9/downloading-media/downloading-multiple-files)

Advanced usage
--------------

- [ Working with multiple filesystems ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/working-with-multiple-filesystems)
- [ Using custom properties ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/using-custom-properties)
- [ Storing media specific manipulations ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/storing-media-specific-manipulations)
- [ Using your own model ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/using-your-own-model)
- [ Outputting media ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/outputting-media)
- [ Rendering media ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/rendering-media)
- [ Using a custom directory structure ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/using-a-custom-directory-structure)
- [ Ordering media ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/ordering-media)
- [ Using a custom media downloader ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/using-a-custom-media-downloader)
- [ Moving media ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/moving-media)
- [ Consuming events ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/consuming-events)
- [ Generating custom urls ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/generating-custom-urls)
- [ Overriding default filesystem behavior ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/overriding-the-default-filesystem-behaviour)
- [ Naming generated files ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/naming-files)
- [ Disable CDN ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/disable-cdn)
- [ Customising Database Connections ](https://spatie.be/docs/laravel-medialibrary/v9/advanced-usage/customising-database-connections)

API
---

- [ Adding files ](https://spatie.be/docs/laravel-medialibrary/v9/api/adding-files)
- [ Defining conversions ](https://spatie.be/docs/laravel-medialibrary/v9/api/defining-conversions)

      You are viewing the documentation for **an older version** of this package. You can check the version you are using with the following command:

 `                                    composer show spatie/laravel-medialibrary                                                                                                                                                                                                                                    `

Processing uploads on the server
================================

###  On this page

1. [ Are you a visual learner? ](#content-are-you-a-visual-learner)
2. [ Enabling temporary uploads ](#content-enabling-temporary-uploads)
3. [ Setting up the view &amp;amp; controller ](#content-setting-up-the-view--controller)
4. [ Validation ](#content-validation)
5. [ Validating requests ](#content-validating-requests)
6. [ Processing responses ](#content-processing-responses)
7. [ Customizing the preview images ](#content-customizing-the-preview-images)

All Blade, Vue and React components communicate with the server in the same way. After a user selects one or more files, they're immediate sent to the server and stored as temporary uploads. When the parent form is submitted, the media items can be attached to a model.

Are you a visual learner?
---------------------------------------------------------------------------------------------------------------------------------

This video shows you how Media Library Pro uses temporary uploads under the hood.

Want to see more videos like this? Check out our [free video course on how to use Laravel Media Library](https://spatie.be/videos/discovering-laravel-media-library).

Enabling temporary uploads
--------------------------------------------------------------------------------------------------------------------------------------

Plain HTML file ``s have two major shortcomings: they only upload the file when the form is submitted, and they're unable to remember the file when a form fails to submit. Temporary uploads solve both these problems.

When a user selects or drops a file in one of the Media Library components, it gets uploaded to the server immediately. Problem number 1 solved!

If the form submission fails later on, Media Library will pass down the previously added temporary upload objects so it can prefill the component with the previously uploaded files. Problem number 2 solved too!

To set up temporary uploads, register the temporary uploads route with our handy macro.

```
// Probably routes/web.php

Route::mediaLibrary();
```

This will register a route at `/media-library-pro/uploads`.

### Enabling Vapor support

If use React or Vue components to handle uploads you must set the `enable_vapor_uploads` key in the `media-library` config file to `true`. When enabling this option, a route will be registered that will enable the Media Library Pro Vue and React components to move uploaded files in an S3 bucket to their right place.

With the config option enabled, the `Route::mediaLibrary();` will register a route at `/media-library-pro/post-s3`instead of `/media-library-pro/uploads`.

### Customizing the upload URL

You can customize the upload url by passing a base url to the macro.

```
// Probably routes/web.php

Route::mediaLibrary('my-custom-url');
```

This will register a route at `/my-custom-url/uploads`

Setting up the view &amp; controller
----------------------------------------------------------------------------------------------------------------------------------------------------------

After a user has added files and they've been stored as temporary uploads, the user will submit the form. At this point the form request will hit one of your application's controllers. This is where you can permanently attach the file to your models.

To illustrate, we'll set up a little profile screen where a user may upload their avatar.

```
// Back in routes/web.php
use App\Http\Controllers\ProfileController;

Route::get('profile', [ProfileController::class, 'edit']);
Route::post('profile', [ProfileController::class, 'store']);

Route::mediaLibrary();
```

The profile controller has a simple form that uses the Blade attachment component.

```
{{-- resources/views/profile.blade.php --}}

```

And, assuming you're familiar with the [basic usage](../basic-usage) of the Media Library, this is how we'd store the uploaded avatar on the user.

```
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class ProfileController
{
    public function edit()
    {
        return view('profile', [$user => Auth::user()]);
    }

    public function store(Request $request)
    {
        $user = Auth::user();

        $user
            ->addFromMediaLibraryRequest($request->avatar)
            ->toMediaCollection('avatar');
    }
}
```

Validation
--------------------------------------------------------------------------------------

The `ProfileController` we built assumes users will only upload the exact file types we're looking for. Of course they won't! We need to validate the incoming media before attaching them to our models.

The Media Library components provide instant client-side validation. You'll read more about that in the component docs. First, we'll set up server-side validation.

To validate uploaded media, we'll use create a custom form request.

```
-  public function store(Request $request)
+  public function store(ProfileRequest $request)
```

```
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Spatie\MediaLibraryPro\Rules\Concerns\ValidatesMedia;

class ProfileRequest extends FormRequest
{
    use ValidatesMedia;

    public function rules()
    {
        return [
            'images' => $this
                ->validateMultipleMedia()
                ->minItems(1)
                ->maxItems(5)
                ->extension('png')
                ->maxItemSizeInKb(1024)
                ->attribute('name', 'required')
        ];
    }
}
```

---

Every component will pass data in a key of a request. The name of that key is the name you passed to the `name` prop of any of the components.

```
// data will get passed via the `avatar` key of the request.

```

The content of that request key will be an array. For each file uploaded that array will hold an array with these keys.

- `name`: the name of the uploaded file
- `uuid`: the UUID of a `Media` model. For newly uploaded files that have not been associated to a model yet, the `Media` model will be associated with a `TemporaryUpload` model
- `order`: the order in which this item should be stored in a media collection.

Validating requests
-----------------------------------------------------------------------------------------------------------------

Even though the upload components do some validation of their own, we highly recommend always validating requests on the server as well.

You should handle validation in a form request. On the form request you should use the `Spatie\MediaLibraryPro\Rules\Concerns\ValidatesMedia` trait. This will give you access to the `validateSingleMedia` and `validateMultipleMedia` methods.

In this example we assume that a component was configured to use the `images` key of the request. We validate that there was at least one item uploaded, but no more than 5. Only `png`s that are up to 1MB in size are allowed. All images should have a name.

```
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Spatie\MediaLibraryPro\Rules\Concerns\ValidatesMedia;

class MyRequest extends FormRequest
{
    use ValidatesMedia;

    public function rules()
    {
        return [
            'images' => $this
                ->validateMultipleMedia()
                ->minItems(1)
                ->maxItems(5)
                ->extension('png')
                ->maxItemSizeInKb(1024)
                ->attribute('name', 'required')
        ];
    }
}
```

If you are only allowing one uploaded file, you can use the `validateSingleMedia` in much the same way.

```
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Spatie\MediaLibraryPro\Rules\Concerns\ValidatesMedia;

class MyRequest extends FormRequest
{
    use ValidatesMedia;

    public function rules()
    {
        return [
            'avatar' => $this
                ->validateSingleMedia()
                ->extension('png')
                ->maxItemSizeInKb(1024)
        ];
    }
}
```

These are the available validation methods on `validateSingleMedia() ` and `validateMultipleMedia`

- `minSizeInKb($minSizeInKb)`: validates that a single upload is not smaller than the `$minSizeInKb` given
- `maxSizeInKb($maxSizeInKb)`: validates that a single upload is not greater than the `$minSizeInKb` given
- `extension($extension)`: this rule expects a single extension as a string or multiple extensions as an array. Under the hood, the rule will validate if the value has the mime type that corresponds with the given extension.
- `mime($mime)`: this rule expects a single mime type as a string or multiple mime types as an array.
- `itemName($rules)`: This rule accepts rules that should be used to validate the name of a media item.
- `customProperty($name, $rules)`: this rule accepts a custom property name and rules that should be used to validate the attribute
- `dimensions($width, $height)`: validates that the image has a specific width and height (in pixels).
- `width($width)`: validates that the image has a specific width (in pixels). The height is not validated.
- `height($height)`: validates that the image has a specific height (in pixels). The width is not validated.
- `widthBetween($minWidth, $maxWidth)`: validates that the image width (in pixels) is between the `$minWidth` and `$maxWidth` given (inclusive)
- `heightBetween($minHeight, $maxHeight)`: validates that the image height (in pixels) is between the `$minHeight` and `$maxHeight` given (inclusive)

These rules can be used on `validateMultipleMedia`;

- `minTotalSizeInKb($maxTotalSizeInKb)`: validates that the combined size of uploads is not smaller than the `$minTotalSizeInKb` given
- `maxTotalSizeInKb($maxTotalSizeInKb)`: validates that the combined size of uploads is not greater than the `$maxTotalSizeInKb` given

### Validating attributes and custom properties

If you're [using custom properties](/docs/laravel-medialibrary/v9/handling-uploads-with-media-library-pro/handling-uploads-with-blade#using-custom-properties), you can validate them with the `customProperty` function. The first argument should be the name of the custom property you are validating. The second argument should be a string or an array with rules you'd like to use.

Here's an example where we validate `extra_property` and `another_extra_property`.

```
use Illuminate\Foundation\Http\FormRequest;
use Spatie\MediaLibraryPro\Rules\Concerns\ValidatesMedia;

class StoreLivewireCollectionCustomPropertyRequest extends FormRequest
{
    use ValidatesMedia;

    public function rules()
    {
        return [
            'name' => 'required',
            'images' => $this->validateMultipleMedia()
                ->customProperty('extra_field', 'required|max:50')
                ->customProperty('another_extra_property', ['required', 'max:50'])
        ];
    }
}
```

Processing responses
--------------------------------------------------------------------------------------------------------------------

After you've validated the response, you should persist the changes to the media library. The media library provides two methods for that: `syncFromMediaLibraryRequest` and `addFromMediaLibraryRequest`. Both these methods are available on all [models that handle media](/docs/laravel-medialibrary/v9/basic-usage/preparing-your-model).

### `addFromMediaLibraryRequest`

This method will add all media whose `uuid` is in the response to a media collection of a model. Existing media associated on the model will remain untouched.

You should probably use this method when only accepting new uploads.

```
// in a controller

public function yourMethod(YourFormRequest $request)
{
    // retrieve model

    $yourModel
        ->addFromMediaLibraryRequest($request->get('images'))
        ->toMediaCollection('images');

    flash()->success('Your model has been saved.')

    return back();
}
```

### `syncFromMediaLibraryRequest`

You should use this method when you are using the `x-media-library-collection` Blade component (or equivalent Vue or React component).

Here is an example where we are going to sync that the contents of the `images` key in the request to the media library. In this example we use the `images` key, but of course you should use the name that you used.

All media associated with `$yourModel` whose `uuid` is not present in the `images` array of the request will be deleted.

```
// in a controller

public function yourMethod(YourFormRequest $request)
{
    // retrieve model

    $yourModel
        ->syncFromMediaLibraryRequest($request->images)
        ->toMediaCollection('images');

    flash()->success('Your model has been saved.')

    return back();
}
```

After this code has been executed, the media, whose `uuid` is present in the `images` array of request, will be in the `images collection of `$yourModel`.

```
$yourModel->getMedia('images'); // the media that we just synced will be returned.
```

### Handling custom properties

If you are using properties for your media items you should pass the names of the custom properties you expect to the `withCustomProperties` method. Only these custom properties will be accepted.

```
$yourModel
    ->syncFromMediaLibraryRequest($request->images)
    ->withCustomProperties('extra_field', 'another_extra_field')
    ->toMediaCollection('images');
```

### Setting a name

If you want use a specific media name before adding it to disk you can use the `usingName` method.

```
$yourModel
    ->addFromMediaLibraryRequest($request->images)
    ->usingName('my custom name')
    ->toMediaCollection('images');
```

Alternatively, you can pass a callable to `usingName`. This callable accepts an instance of `Spatie\MediaLibraryPro\MediaLibraryRequestItem` which can be used to get properties of the uploaded file.

In this example we're going to lowercase the name of the uploaded file before adding it the media library.

```
$yourModel
    ->addFromMediaLibraryRequest($request->images)
    ->usingName(fn(MediaLibraryRequestItem $item) => strtolower($item->name))
    ->toMediaCollection('images');
```

### Setting a file name

If you want to rename an uploaded file before adding it to disk you can use the `usingFileName` method.

```
$yourModel
    ->addFromMediaLibraryRequest($request->images)
    ->usingFileName('myFile.jpg')
    ->toMediaCollection('images');
```

Alternatively, you can pass a callable to `usingFileName`. This callable accepts an instance of `Spatie\MediaLibraryPro\MediaLibraryRequestItem` which can be used to get properties of the uploaded file.

In this example we're going to lowercase the name of the uploaded file before adding it the media library.

```
$yourModel
    ->addFromMediaLibraryRequest($request->images)
    ->usingFileName(fn(MediaLibraryRequestItem $item) => strtolower($item->name))
    ->toMediaCollection('images');
```

Customizing the preview images
--------------------------------------------------------------------------------------------------------------------------------------------------

All Blade, Vue and React components will display previews images that are generated by the `preview` conversion of the `TemporaryUpload` model. This conversion will create a 500x500 representation of the image.

You can customize this by registering a preview manipulation. Typically, this would be done in a service provider. Here's an example where we will create 300x300 previews

```
use Spatie\MediaLibraryPro\Models\TemporaryUpload;
use Spatie\MediaLibrary\Conversions\Conversion;
use Spatie\Image\Manipulations;

// in a service provider
TemporaryUpload::previewManipulation(function(Conversion $conversion) {
    $conversion->fit(Manipulations::FIT_CROP, 300, 300);
});
```

The components will use the `preview` conversion of models that have made associated to them. For example, if you have a `$blogPost` model, and you use the components to display the media associated to that model, the components will use `preview` conversion on the `BlogPost` model.

Make sure such an `preview` conversion exists for each model that handles media. We highly recommend to use `nonQueued`so the image is immediately available.
