Laravel upload files to S3
Thanks to the Storage Facade in Laravel, interacting with files is now a lot more straightforward. In past implementations of file upload, I sent the file to the same server as my Laravel API, in order to upload it to S3. That worked out ok, you can upload the file like this:
$file->storeAs($basePath, $uuid . '.' . $file->extension(), 's3');
This worked quite well for small files — I just kept a database table of file_uploads
to store where each file was now located within S3.
Now I have a new situation where the file is coming from another server, and they are quite large. There is no real reason to hit the server with every file upload only to forward it to S3. You can use presigned URLs to place the file directly into S3.
What is a presigned URL?
The main purpose of presigned URLs is to grant a user temporary access to an S3 object.
A presigned URL is generated by an AWS user who has access to the object. The generated URL is then given to the unauthorized user. The presigned URL can be entered in a browser or used by a program or HTML webpage. The credentials used by the presigned URL are those of the AWS user who generated the URL. A presigned URL remains valid for a limited period of time which is specified when the URL is generated.
In other words, our client asks the API for a presigned URL and uses that URL to upload the file to s3.
Generating a presigned URL in Laravel
First of all, you should install the S3 package for laravel:
composer require league/flysystem-aws-s3-v3 "~1.0"
Then make an endpoint for generating a pre-signed URL:
This will generate a pre-signed URL that you can use to upload a file using a PUT request. To download a file simply use GetObject
instead of PutObject
on line 11.
Uploading metadata
If you want to upload metadata with your file, you can use another parameter like this:
In your S3 bucket you can navigate to the file, and select it you should see this metadata value under ‘User defined’:
Retrieving metadata
To retrieve metadata you will need to parse the headers from the presigned URL:
Get all files in a folder
If you want to list all the files in a given folder:
$files = Storage::disk('s3')->files($folder);
This will give the full file paths of every file in the folder as an array of strings.
Cloud storage is becoming increasingly popular as some of the file upload risks are minimized due to files no longer having to be stored on the same server as your application. presigned URLs help even further as there is no need to send your file to your application server before pushing it to S3. I hope this post will help you as you work with Laravel and S3. Thanks for reading!