How to upload file to S3 bucket in laravel?

How to upload file to S3 bucket in laravel?

Many who are new to laravel will have this question: How to upload files to S3 bucket in laravel? Well let me tell you, It’s pretty simple. Laravel has a built-in driver for S3 into it’s file system module and in this tutorial we will use that.

We just have to tell Laravel to use S3 as a storage disk and that’s all. Well there are minor S3 specific configurations that need to be done.

First of all, We need to install S3 driver package, so let’s do that first using this command:

composer require league/flysystem-aws-s3-v3 “^1.0”

Now that it’s done, let’s see some code to understand how we can use S3 as a storage disk to upload file to S3 bucket in laravel.

You can get working example from my github via following link:

Go to repository

First, We need AWS Credentials (AWS_ACCESS_KEY_ID & AWS_SECRET_ACCESS_KEY) same you can get from AWS under IAM (You need to create separate user with programmatic access and who has sufficient permission to S3 bucket).

We also need one bucket where we want our files to be stored, If you don’t have one then you can create new bucket and use that.

So, Our .env should be updated accordingly and should look like this :

AWS_ACCESS_KEY_ID=****
AWS_SECRET_ACCESS_KEY=****
AWS_DEFAULT_REGION=ap-south-1 (can be different for you)
AWS_BUCKET=<your-bucket-name>
AWS_USE_PATH_STYLE_ENDPOINT=false

Once our AWS configuration has been done, let’s use Laravel’s Storage Facade to upload files in our S3 bucket.

public function upload(Request $request) {

   if (!$request->hasFile('user_file')) {
       return Response::json([
           'status' => false,
           'message' => 'You have not provided the valid file'
       ]);
   }

   $file = $request->file('user_file');

   // We can get following parameters that can be stored for future use as per your requirement
   $originalFileName = $file->getClientOriginalName();
   $originalFileExtension = $file->getClientOriginalExtension();
   $fileMime = $file->getMimeType();
   $fileContent = $file->getContent(); // File binary data

   try {
       // For S3 Bucket, we need to provide full path, for this example, we will store all user uploaded files
       // in user-files directory and so filename will be as follow.
       $filenameForS3 = 'user-files/' . $originalFileName;

       // You need to install following package for S3 file system to work
       // composer require league/flysystem-aws-s3-v3 "^1.0"
       $response = Storage::disk('s3')->put($filenameForS3, $fileContent, []);

       if ($response) {
           return Response::json([
               'status' => true,
               'message' => 'File has been uploaded successfully'
           ]);
       }

       return Response::json([
           'status' => false,
           'message' => 'There was an error while uploading your file'
       ]);
   } catch (S3Exception $ex) {
       return Response::json([
           'status' => false,
           'message' => 'There was an error while uploading your file',
           'error_message' => $ex->getAwsErrorMessage() // We should probably log this instead of providing it in response.
       ]);
   }
}

Above code is self explanatory, Same we can use storage facade to retrieve file from S3 Bucket.

public function getFile(Request $request) {

   if (!$request->has('file_name')) {
       return Response::json([
           'status' => false,
           'message' => 'You have not provided the valid filename'
       ]);
   }

   $originalFileName = $request->get('file_name');

   $filenameForS3 = 'user-files/' . $originalFileName;

   try {
       if (!Storage::disk('s3')->exists($filenameForS3)) {
           return Response::json([
               'status' => false,
               'message' => 'File with provided name does not exist',
           ]);
       }

       // If you want to use binary data, then you can use get method
       // $response = Storage::disk('s3')->get($filenameForS3);

       // If you want to get permanent url then you can use url method, For this URL to work, your file should have public access.
       // $response = Storage::disk('s3')->url($filenameForS3);

       // We can use temporaryUrl method to generate signed URL, this is temporary URL that will be unvalidated once it's expired.
       // This URL will work even if your file does not have public access and is secure way to store and share your files.
       $response = Storage::disk('s3')->temporaryUrl($filenameForS3, now()->addMinutes(30));

       if ($response) {
           return Response::json([
               'status' => true,
               'message' => 'Your file is retrieved successfully',
               'file_url' => $response
           ]);
       }

       return Response::json([
           'status' => false,
           'message' => 'There was an error while retrieving your file'
       ]);
   } catch (S3Exception $ex) {
       return Response::json([
           'status' => false,
           'message' => 'There was an error while retrieving your file',
           'error_message' => $ex->getAwsErrorMessage() // We should probably log this instead of providing it in response.
       ]);
   } catch (FileNotFoundException $ex) {
       return Response::json([
           'status' => false,
           'message' => 'File with provided name does not exist',
       ]);
   }
}

You see it’s very easy to upload file to S3 bucket in laravel, Laravel makes it very easy to upload and retrieve files from S3 bucket. We can achieve the same using AWS PHP SDK if we require more control.

0 0 votes
Article Rating
guest
0 Comments
Inline Feedbacks
View all comments