Skip to content
Advertisement

Laravel can’t connect to AWS S3

I have set up an S3 bucket and created an IAM user with full S3 access permission, and ran composer require league/flysystem-aws-s3-v3.

I have also have configured the following in .env:

AWS_ACCESS_KEY_ID=XXXX
AWS_SECRET_ACCESS_KEY=YYYY
AWS_DEFAULT_REGION=us-west-3
AWS_BUCKET=my-bucket
AWS_USE_PATH_STYLE_ENDPOINT=false
FILESYSTEM_DRIVER=s3

The problem is that I can’t interact with S3 at all from my controller. I’ve tried sending files to S3:

$path = $request->Image->store('images', 's3');

I have also manually uploaded an image to S3, then tried to check if it can find it:

if (Storage::disk('s3')->exists('photo.jpg')) {
dd("file found");
} else{
dd("file not found");
}

This results in this error: Unable to check existence for: photo.jpg

This makes me think that the issue is with flysystem-aws-s3-v3.

Is there a way to narrow down where the issue resides? by the way, I’m using Laravel 9 and flysystem-aws-s3-v3 3.0 if that helps.

Advertisement

Answer

I finally found the reason why the connection didn’t work. This is how the .env file looked like:

//some env vars

AWS_ACCESS_KEY_ID=XXXX
AWS_SECRET_ACCESS_KEY=YYYY
AWS_DEFAULT_REGION=us-west-3
AWS_BUCKET=my-bucket
AWS_USE_PATH_STYLE_ENDPOINT=false
FILESYSTEM_DRIVER=s3

//many other env vars

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=

It turns out that Laravel (or maybe it was Flysystem?) already configured the same S3 variables and left the values empty. So my environment variables were getting overridden by these empty ones, leaving the connection to fail. I guess the lesson to learn here is to always check your entire .env file if it contains multiple vars with the same key.

Bonus

After setting up S3 with Laravel, you could use these snippets to:

  • Save an image to your S3 bucket:
Storage::disk('s3')->put($newImagePath, file_get_contents($imageName));
 //make sure to include the extension of the image in the $imageName, to do that, use $Image->extension()
  • Get an image from your S3 bucket:
$image =  Storage::disk('s3')->temporaryUrl($imagePath, Carbon::now()->addMinutes(20));   //tip: if you get a squiggly line on tempraryUrl(), it's just Intelephense shenanigans, you can just ignore it or remove it using https://github.com/barryvdh/laravel-ide-helper 
//This will generate a temporary link that your Blade file can use to access an image, this link will last for 20 minutes. 
//This will work even with S3 images stored with Private visibility.

//In your blade file:
<img src="{{$image}}">
  • Check if an image exists in your S3 bucket:
if (Storage::disk('s3')->exists($imagePath)) {  //make sure to include the full path to the image file in $imagePath
//do stuff
}
  • Delete an image from your S3 bucket:
Storage::disk('s3')->delete($imagePath);
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement