AWS S3 and Laravel Filesystem

When we want to build a real scalable Laravel app and don’t save users’ files in app storage — we will need to use an AWS S3 Bucket service. So what’s this means and how this works?

How does AWS S3 Bucket work?

If you haven’t heard anything about Amazon Web Services, I’ll tell you what it is. So in short words, we can describe AWS as a big toolbox with many services that we can use for hosting apps, creating web servers, running virtual machines, and other cool things. There are many web services that we can use for our projects, but in this article — I’m gonna show you how you can use S3 Bucket.

We can describe this service as virtual storage that we create on Amazon Servers to save some data that we want. But how does it works? Down below you can see the schema of the S3 Bucket logic:

First, we are uploading files by application, then the file moves to the internet, and after that file is uploaded to the Amazon S3 Bucket. Easy 😎 Now that we know a really simple algorithm for how this works — it’s time to create a new instance for Amazon S3 Bucket.

Create a new S3 Bucket instance

Open your Amazon Web Services console and go to the S3 Bucket services, and click on the “Create bucket” button:

We can create a new instance with default settings. Now let’s go to the IAM and create a new user with an access key for the app:

Don’t forget to click on the “Access key” checkbox to get access keys at the end of the user creation. And I already created a new group with full S3 permissions (don’t forget to create a new user group and policy with full access to S3 Bucket)— so I’m gonna choose this group in the next step:

Let’s live tags empty, and in the last, we will get access key and secret keys that we are going to use to connect to our bucket when we will configuring a new laravel app:

Copy these two keys and save it — we gonna use them for the AWS S3 Bucket connection. Great, now we have everything that we need to connect laravel to the bucket instance that we created.

Creating a new laravel app

Okay, now we have bucket and access keys for this bucket, so it’s time to create a new laravel app and configure the “.env” file:

$ composer create-project laravel/laravel aws-laravel

After the creation of the new Laravel App — you should open your “.env” file and type connection data for the AWS variables:

# You don't need to create all these variables,
# they already created in the .env file

AWS_ACCESS_KEY_ID=your-user-acces-key-here
AWS_SECRET_ACCESS_KEY=your-user-secret-key-here
AWS_DEFAULT_REGION=eu-west-2
AWS_BUCKET=laravel-bucket-tutorial # name of your bucket
AWS_USE_PATH_STYLE_ENDPOINT=false# And you can also change default disk of the filesystem
FILESYSTEM_DISK=s3

Okay, now let’s create a new controller where we gonna test file upload by using the Storage facade class:

$ php artisan make:controller DiskController

And yes, we also need to install one important package to work with AWS:

$ composer require league/flysystem-aws-s3-v3 "^3.0"

Let’s write the next code in the “DiskController” that we just created:

<?php

namespace App\Http\Controllers;

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

class DiskController extends Controller
{
public function index()
{
Storage::put('test1.txt', 'test again');

// If you didn't setup S3 as default disk in .env file
$contents = Storage::disk('s3')->get('test1.txt');

var_dump( $contents ); // This will show "test again text"
}
}

Cool, now let’s open routes/web.php and let’s create a new route for this index function:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\DiskController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::get('/disk', [DiskController::class, 'index']);

Let’s start the local server of the app and let’s check the /disk page:

$ php artisan serve

And that’s what you will see:

If you open your S3 Bucket console, you can see that file “test1.txt” is created and saved in your bucket 💥🪣!

Summary

As you can see — that’s not hard to connect your application to the S3 Bucket and start uploading files by using a Storage facade. Maybe you will write your own classes to build a more flexible architecture for the app that will always work with AWS S3 bucket, or for example, create your own Service that will process all upload operations. Soon you will see a more complex tutorial by me about AWS and Laravel filesystem. So, thanks for reading 😎