So you have your killer new application planned out in Laravel, you get everything working with local uploads for that fancy image feature you need. Then bummer, you realize something. With a lot of hosts now shifting to
Amazon S3 To The Rescue
Or any other good cloud storage provider. I’m looking at you Rackspace.
Amazon S3 is cheap, pretty simple to use and (along with Rackspace) has built in support within Laravel 5. We are going to take a look at how you can upload your image straight up to Amazon S3 storage.
Let’s get straight into this. I’m assuming you have your own controller setup, and we will only be taking a look at the method that responds to the
POST request. Importantly though this code will work if you want to use a bulk uploader such as Plupload. Just be aware that every image uploaded (obviously) will count as a request to your S3 bucket.
First thing we need to do is get ourselves the package to push to S3. To do that we need to use Composer. Just run:
composer require league/flysystem-aws-s3-v3 ~1.0
Once it’s complete pop yourself over to the
config/filesystems.php file and enter your Amazon S3 information. I’m not going to cover setting up your bucket or anything as that is covered extremely well over at Amazon. I will however tell you to take their advice and use their user system so you aren’t using your Root keys in your application… It’s normally (pretty much always) a really bad idea.
Now we can write our code. I’ve given you all the code needed to upload an image, it isn’t the only way it can be done & this assumes your response needs to be JSON (handy if using a mass uploader that needs JSON as a response).
public function store(Gallery $gallery, Request $request)
return Response::json(['error' => 'No File Sent']);
return Response::json(['error' => 'File is not valid']);
$file = $request->file('file');
$v = Validator::make(
['file' => 'required|mimes:jpeg,jpg|max:8000']
return Response::json(['error' => $v->errors()]);
//input a row into the database to track the image (if needed)
$image = $gallery->images()->create([
'id' => null,
'ext' => $request->file('file')->guessExtension()
//Use some method to generate your filename here. Here we are just using the ID of the image
$filename = $image->id . '.' . $image->ext;
//Push file to S3
Storage::disk('s3')->put('uploads/' . $filename, file_get_contents($file));
//Use this line to move the file to local storage & make any thumbnails you might want
//Thumbnail as needed here. Then use method shown above to push thumbnails to S3
//If making thumbnails uncomment these to remove the local copy.
//if(Storage::disk('s3')->exists('uploads/' . $filename))
//Storage::disk()->delete('uploads/' . $filename);
//If we are still here we are good to go.
return Response::json(['OK' => 1]);
The code has been generalised to suit most situations, you’ll need to customise where needed. Things like filename generation, and entering rows into the database are obviously dependant upon your project.
That’s actually all there is to it. Your files will now be placed straight into your bucket on Amazon S3. Awesome, huh?
There are actually a few things that can go wrong when trying to push to S3 with Laravel, so I’m going to cover some common solutions here.
Nothing is Happening / Logs Show Connection Error
This is generally caused by something being incorrect in your config. This is generally either a misspelling, the key being incorrect, or the region being incorrect. Remember if you choose a location like Ireland for your bucket, your region is actually EU West 1 (eu-west-1) not Ireland. There is a list available on Amazon so you can confirm.
Image Appears In Storage Folder
You haven’t given a disk name when accessing the Storage facade. This shouldn’t happen if you use the code as written above, but can happen when writing your own code. If you are tired, or forget when writing it can be a painful mistake to make.
I Want To Make Thumbnails Too
Then uncomment the lines that are commented out in the code snippet & then thumbnail as you wish. Once finished push them in the same way the larger image has been. Remember you must always push your larger file to S3 first as the
put method on the Storage facade copies the image to the server, the
move method called from the file actually physically moves the image so it can no longer be accessed via
file_get_contents() without pointing to it’s new location.
How Can I Link To My Files
Ahh, this is a good one. I might be wrong, but as far as I’m aware there is no ‘simplez’ method of doing this. You could piece together the URL by pulling your region from your filesystem config using
Config::get('filesystems.disks.s3.region') and similar for bucket, since the URL is essentially
I did however find another way. It may, or may not be a good way, but after some digging through the core code I found you could access the
getObjectUrl() method on the Amazon SDK used by Laravel. That is done by doing the following:
$bucket = Config::get('filesystems.disks.s3.bucket');
$s3 = Storage::disk('s3');
$key is the path to the file inside the bucket. If you have a helper class for something like this you could make yourself a small method & set the disk & bucket as variables via the Construct. How you do it though is completely up to you.
If you come across any other issues feel free to ask in the comments & I’ll see if I can help. In the meantime go forth & populate your Amazon S3 bucket with images from your awesome applications.
 Yes, I am aware the method is called from the
UploadedFile Symfony class, which extends the PHP
SplFileInfo class. That’s a mouth-full though, which is why it is down here & not in the main article.