File uploads are one of the vital pieces in most spider web projects, and Laravel has awesome functionality for that, just information is pretty fragmented, especially for specific cases. I decided to gather it all under 1 big manufactures, discussing the about painful tasks related to file uploads. Enjoy!

Hither are the topics nosotros volition hash out in the article:

  1. Uncomplicated "local" file upload
  2. File validation procedure
  3. Uploading to external disks: Amazon S3 example
  4. AJAX upload and multiple files at once
  5. Image manipulation: crop, resize etc.

1. Local file upload

Let'south start from the nuts – how does Laravel deal with it by default? It'southward pretty easy.

So, we have a elementary form:

<form action="{{ route('books.store') }}" method="Postal service" enctype="multipart/form-information">     {{ csrf_field() }}     Book title:     <br />     <input type="text" name="title" />     <br /><br />     Logo:     <br />     <input type="file" name="logo" />     <br /><br />     <input blazon="submit" value=" Salve " /> </form>        

And this is a simple code to upload that logo.

public function store(Request $request) {     $request->logo->store('logos'); }        

Later on this sentence, file is actually stored in the folder storage/app/logos:

You can specify the folder where the file should exist uploaded – see parameter 'logos'.

As you tin see, Laravel generated a random filename, but you tin easily override it – use function storeAs():

$request->logo->storeAs('logos', 'i.png');        

Or, you can keep the original filename:

$request->logo->storeAs('logos', $request->logo->getClientOriginalName());        

Storage binder: files are not public?

Nosotros saw that, past default, Laravel stores the file in /storage/app folder. Why?

It'south actually washed with a good plan – to hide uploaded files from users by default, to avoid illegal access or scraping.

Besides, you may ask how to show the file then, if /storage binder is non attainable in the browser? It's not public, right?

If you practise want those files to be public, yous need to change ii things:

1. Config deejay change. Change config/filesystems.php parameter 'default' – from 'local' to 'public': and so the files volition be stored in storage/app/public (we will talk almost filesystems settings later);

ii. Symlink. Put a symlink from /public/storage to /storage/app/public binder, with i Artisan command:

php artisan storage:link

Here's an excerpt from the official Laravel docs on this:

Past default, the public disk uses the local driver and stores these files in storage/app/public. To make them accessible from the web, you should create a symbolic link from public/storage to storage/app/public.

At present, we can access the file from our example:

Another mode, of class, is to cheque access in your Laravel code and so return the file equally downloaded stream.

// This will come from database in reality $filename = 'onvuqaJkKWx6ShRSserOR8p5HAE4RE3yJPCeAdrO.png';  if (!auth()->check()) {     return abort(404); } render response()->download(storage_path('app/public/logos/' . $filename));        

In this case, actual users won't even know the actual filename until download, and then you're in control over the access to that file.

Finally, if you lot desire to delete the file, yous should apply Storage facade for it:

use Illuminate\Support\Facades\Storage;  $filename = 'onvuqaJkKWx6ShRSserOR8p5HAE4RE3yJPCeAdrO.png'; Storage::delete('logos/' . $filename);        

This is pretty much all the information we go from the official Laravel documentation about file upload. But in reality, it's only the start. Let'south dive deeper.


2. File validation

Laravel has quite a lot of validation rules, that tin can exist stored in Request classes, some of them are related to files.

For case, if yous desire to cheque for successfully uploaded file you may check this.

class StoreBookRequest extends FormRequest {     public role rules()     {         return [             'logo' => 'required|file',         ];     } }        

This rule file means: The field nether validation must exist a successfully uploaded file.

Here are more than rules related to files:

image:
The file nether validation must exist an epitome (jpeg, png, bmp, gif, or svg)


mimes:jpeg,bmp,png,…:
The file under validation must have a MIME type corresponding to i of the listed extensions.

Even though yous merely need to specify the extensions, this rule really validates against the MIME blazon of the file by reading the file's contents and guessing its MIME type.

A full listing of MIME types and their corresponding extensions may be found at the post-obit location: https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types


mimetypes:text/plain,…:
The file under validation must match i of the given MIME types.

'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'

To determine the MIME type of the uploaded file, the file'southward contents will be read and the framework will attempt to guess the MIME blazon, which may be different from the client provided MIME blazon.


size:value
The field nether validation must accept a size matching the given value. For files, size corresponds to the file size in kilobytes.


dimensions:

The file under validation must be an epitome meeting the dimension constraints as specified past the dominion'southward parameters:

'avatar' => 'dimensions:min_width=100,min_height=200'

Available constraints are: min_width, max_width, min_height, max_height, width, elevation, ratio.

A ratio constraint should exist represented equally width divided past height. This can be specified either by a statement like 3/2 or a float like ane.5:

'avatar' => 'dimensions:ratio=iii/two'

You lot can check other validation rules for Laravel here.

Notice. Important annotation about size validation – don't forget to bank check your php.ini settings. By default, y'all can upload files but up to 2mb.

upload_max_filesize = 2M

Also, check maximum POST request size:

post_max_size = 8M

Merely be conscientious with putting bigger numbers here, it can be used in wrong ways past some people. To upload much bigger files, you tin utilise chunks, we will talk over it separately later.


3. Uploading to external disks: Amazon S3

Disks and Drivers.

And then far, in this article we touched on the basic file upload to the same code repository – into the /storage binder. But quite oftentimes it makes sense to shop files separately, especially if they are bigger and could take upwardly server deejay infinite.

Let's meet two new concepts of Filesystem: drivers and disks.

Driver is a type of storage.
Laravel supports these drivers out of the box:

  • local: default one we used then far
  • ‎s3: represents popular Amazon S3, requires boosted package league/flysystem-aws-s3-v3
  • ‎rackspace: represents Rackspace Cloud storage, requires boosted parcel league/flysystem-rackspace
  • ftp: you need to setup host/username/password to make information technology work

Ok, these are drivers.

Now, there's another term called disk – it represents the actual folder/bucket name within your called driver.

And yep, it means that one driver can have multiple disks – for example, you want to use one S3 bucket for images, and some other one for documents.

Let'due south look at a default config/filesystems.php settings:

'default' => env('FILESYSTEM_DRIVER', 'local'),  'disks' => [      'local' => [         'driver' => 'local',         'root' => storage_path('app'),     ],      'public' => [         'commuter' => 'local',         'root' => storage_path('app/public'),         'url' => env('APP_URL').'/storage',         'visibility' => 'public',     ],      's3' => [         'driver' => 's3',         'key' => env('AWS_ACCESS_KEY_ID'),         'secret' => env('AWS_SECRET_ACCESS_KEY'),         'region' => env('AWS_DEFAULT_REGION'),         'saucepan' => env('AWS_BUCKET'),     ],  ],        

You lot can see a few things here:

  • Aforementioned driver called local has two different disks – local and public. Remember nosotros changed between the two, in the affiliate higher up?
  • Parameter 'default' points to the deejay that will be used as the main one
  • Delight put your parameters in .env files, to be able to accept different settings for testing and live servers. We've written about .env files here.

So, if you lot want to use S3 as master driver, you need to install league/flysystem-aws-s3-v3 package and modify the .env file:

FILESYSTEM_DRIVER=s3

And then also you tin specify the disk directly in the code of file upload.

$asking->logo->shop('logos', 's3');        

If nosotros practise that and put in our AWS details, here's how our file will be placed in S3 Console.

Now, by default our files volition go public URLs, like this:
https://s3-eu-west-one.amazonaws.com/laraveldaily-videos-examination/logos/OIIB2jilZkhn7wUI6Mol14pgiCtmtxdLUyoZmVKh.png

Is that a security breach? Well, yes and no.

1 of the most popular examples of S3 usage is popular project direction organisation called Trello. If you adhere a file to any card in that location, information technology is stored in S3 and is encoded to really long public URL, like this – see browser URL bar:

And so y'all tin admission the file if you know the name. Here's the official annotate from Trello's aid page:

The URLs for the attachments are cryptographically unguessable, meaning that no one is going to exist able to estimate your attachment URL. However, if you share the URL for a Trello attachment, anyone with the URL will be able to see the attachment.

If you need extra security, nosotros recommend using Google Drive for attachments. Y'all tin can adhere files from Google Drive directly to Trello and specify fine-grained access to the file via the Google Drive interface.

In other words, you can add additional layers to your file storage for security, Trello is just one example of this.

Ok, we're washed with disks/drivers and Amazon S3 example. Let'due south move on to exciting topic of uploading larger files.


four. AJAX upload: Large/multiple files

We've touched briefly on larger file uploads, that information technology makes sense to store them exterior the code, on something like Amazon S3. But there'southward another issue – uploading process, which leaves user waiting for quite a while. Nosotros need to handle it gracefully.

If you just POST a big file via default form, browser will but testify loading signs and you won't get notified about any progress until information technology's done.

We tin change that using AJAX upload and certain library – as an example, I volition take BlueImp JQuery library.

I've recently shot a demo-video for file uploads to Amazon S3:

Also, lawmaking on GitHub: https://github.com/LaravelDaily/Laravel-AmazonS3-Video

Another tutorial I've written is this: Laravel AJAX File Upload with BlueImp JQuery Library

And so I won't repeat those tutorials here, please read them in full particular, but I will just re-cap the main things:

  • You employ JavaScript library to upload files – catch event on click of upload button
  • Every JavaScript library would still need back-stop URL to perform upload – yous can code information technology yourself, or use some Laravel package for upload like Spatie Larvel MediaLibrary
  • It is uploading files in chunks so should work for larger files, too

v. Bonus. Paradigm manipulation: resize/crop/thumbs

Ok, one more final topic. We oft upload images and in that location should be means to manipulate them before/after storing. For example, we need to brand several thumbnails with different sizes – one for the detailed view, one for the list view, and final one equally a small icon.

At that place'south a peachy package for that, recommended by Laravel community and beyond: Intervention Image

This package is non actually for Laravel specifically, it works in full general PHP, as well.

How to install it in Laravel:

composer crave intervention/image

The official documentation too mentions config/app.php changes, but information technology's not needed anymore since Laravel v.v.
You tin use information technology right after the composer control.

At present, what tin nosotros practise with this package? Basically, anything you lot demand with images.

Hither's the most simple example:

use Intervention\Image\Facades\Paradigm;  public function alphabetize() {     $img = Image::make(storage_path('app/logos/i.png'))->resize(300, 200);      return $img->response('jpg'); }        

It volition take the file from storage (where we uploaded it), resize and show it in the browser.

Y'all can also save information technology in different folder for thumbnails:

Image::make(storage_path('app/logos/1.png'))->resize(300, 200)->salvage('1-thumb.png');        

Here are merely a few of the methods that you lot can apply for image manipulation:

And so, merely get creative, read their official documentation and move on to examples like this:

$image->fit(250, 250, function ($constraint) {     $constraint->aspectRatio(); });        

So, we've covered a lot near file uploading in Laravel. I hope you will have a deeper picture now nearly how information technology works.

In our QuickAdminPanel Laravel Generator, we practise use all those three packages mentioned higher up, so you wouldn't have to write the code at all, just enter the details for the field:

See y'all soon in other tutorials for Laravel!