How to Upload Images using Amazon S3 and Laravel
Need to upload images to your S3 instance using Laravel? Luckily Laravel makes it dead simple to setup a connection and start uploading to the cloud. But what does it require on the Amazon end? Strap on your polos and lets get AWS certified. 👌
I'm going to presume you have very basic knowledge of AWS, have an active account with Amazon. If you haven't already, I'd recommend signing up for their 1 year free trial, it's a crazy deal.
The AWS Way
We're going to create an S3 bucket, add the proper policies, and associate an IAM user to it. We'll use Laravel to connect to the S3 bucket through the IAM user's credentials (which is why they need proper permission aka policies).
Bucket Challenge
The first step is to sign in to your AWS account as the root user. Then navigate yourself over to the S3 section of the website.
- Click the blue "+ Create Bucket" button.
- Enter a unique slug for your S3 bucket, select a region for the server, and click next.
- Leave the default settings here, make sure "Manage Public Permissions" selects: "Do not grant public read access..". Click next!
- Click review.
Congrats, you have a new S3 bucket. Now let's assign an IAM user to the bucket.
Time for IAM
We've got to create a new user (or you can use an existing one), and add
a bucket policy allowing your IAM user to upload to the S3
- Create a new user and save their access id and secret.
- Apply a new policy to the user below, replacing "my-bucket" with your bucket slug from earlier:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListAllMyBuckets",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::my-bucket"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::my-bucket/*"
]
}
]
}
If you still get an 'access denied' when viewing files, try adding the following snippet to your policies from Amazon's FAQ:
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"AddPerm",
"Effect":"Allow",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::examplebucket/*"]
}
]
}
Connect with Laravel
Now that we've been able to create a bucket and assign a user to it, let's add the credentials to Laravel so it can connect!
- Open your .ENV file and add the following variables if they don't exist. Make sure to add in your credentials, bucket name, and the bucket's region code:
AWS_ACCESS_KEY_ID=your_key_here
AWS_SECRET_ACCESS_KEY=your_secret_here
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=my-bucket
- Go into your Filesystem config file (
/laravel-project/config/filesystems.php
) and make sure you're using environment variables. Thedisks
array'sS3
array should look like this:'s3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION'), 'bucket' => env('AWS_BUCKET'), ],
That's it! You've connected Laravel to your S3 bucket. Easy right?
Flex My S3
Let's test to see if everything worked! You can see the official Laravel docs for more info on using Filesystems, but you can run a quick test by using the following snippet in a controller:
$my_file = 'file.txt';
$handle = fopen($my_file, 'w') or die('Cannot open file: '.$my_file);
$data = 'Test data to see if this works!';
fwrite($handle, $data);
$storagePath = Storage::disk('s3')->put("uploads", $my_file, 'public');
We create a text file, insert text into it, and upload that text file to the S3 storage. There's also a 3rd parameter on the put
method defined as public, which makes the file publicly accessible. You can remove this to make the file private.
The path to the file on S3 is storage in the $storagePath
variable, so you can store that in your DB and find posts by using Storage::disk('s3')->get($storagePath)
.
All in a days bucket
Laravel makes it effortless to use storage systems like S3, but it's services like AWS that complicate the process with complex policies. I hope this saved you 30 minutes or more of writing and researching IAM policies in the poorly written docs.
Stay regular,
Oscar
Keep Reading: