I finally found the reason why the connection didn't work.
This is how the .env file looked like:
//some env vars here...
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 here...
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:
- Generate a random string as new name for your image file:
$imageName = preg_replace('/[\W]/', '', base64_encode(random_bytes(18)));
- Save an image to your S3 bucket:
Storage::disk('s3')->put($newImagePath, file_get_contents($imageName));
//$imageName is just a string containing the name of the image file and it's extension, something like 'exampleImage.png'
//make sure to include the extension of the image in the $imageName, to do that, concatenate your the name of your image with "." + $Image->extension()
- Get an image from your S3 bucket:
$image = Storage::disk('s3')->temporaryUrl($imagePath, Carbon::now()->addSeconds(40)); //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 40 seconds, this 40 seconds is the period when the image link will be accessible.
//Of course after your image loads onto the browser, even if the image link is gone, the image will remain on the page, reloading the page generates a new image link that works for another 40 seconds.
//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);