Upload files to S3 in Symfony
Install dependencies
Install aws/aws-sdk-php
:
composer require aws/aws-sdk-php
Install vich/uploader-bundle
:
composer require vich/uploader-bundle
Install league/flysystem
:
composer require league/flysystem
Install league/flysystem-aws-s3-v3:
composer require league/flysystem-aws-s3-v3
Configure S3 bucket on AWS
Create an S3 bucket on the AWS console.
Create an IAM user with access to that bucket by assigning it the following policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetObject",
"s3:DeleteObject",
"s3:GetObjectAcl",
"s3:PutObjectAcl",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::<your-s3-bucket-name>",
"arn:aws:s3:::<your-s3-bucket-name>/*"
]
}
]
}
Create an access key to obtain an access key and secret. You’ll use this to authenticate your Symfony app with AWS.

Configure your Aws\S3\S3Client
service
Add the following entry under the services
key in config/services.yaml
:
Aws\S3\S3Client:
arguments:
-
version: 'latest'
region: 'eu-west-2'
credentials:
key: '%env(AWS_S3_ACCESS_KEY)%'
secret: '%env(AWS_S3_ACCESS_SECRET)%'
Replace region
, credentials.key
and credentials.secrets
with the values that make sense for your application.
Configure flysystem S3 storage
Edit config/packages/flysystem.yaml
to something like the below:
# Read the documentation at https://github.com/thephpleague/flysystem-bundle/blob/master/docs/1-getting-started.md
flysystem:
storages:
default.storage:
adapter: 'local'
options:
directory: '%kernel.project_dir%/var/storage/default'
s3_public.storage:
adapter: 'aws'
visibility: public
options:
client: Aws\S3\S3Client
bucket: '%env(AWS_S3_BUCKET)%'
Configure VichUploader to use S3 storage
vich_uploader:
db_driver: orm
storage: flysystem
metadata:
type: attribute
mappings:
media_object:
uri_prefix: ''
upload_destination: 's3_public.storage'
# Will rename uploaded files using a uniqueid as a suffix.
namer: Vich\UploaderBundle\Naming\SmartUniqueNamer
Upload file to S3
To test things work ok, create a dev-only debugging route
- add example debug controller method
<?php
declare(strict_types=1);
namespace App\Controller;
use Aws\S3\S3Client;
use League\Flysystem\FilesystemOperator;
use League\Flysystem\StorageAttributes;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Routing\Attribute\Route;
class DebugController extends AbstractController
{
public function __construct(
private readonly ParameterBagInterface $parameterBag,
private readonly FilesystemOperator $defaultStorage,
private readonly FilesystemOperator $s3PublicStorage,
) {}
#[Route('/debug/s3-client', condition: '"%kernel.environment%" === "dev"')]
public function s3Client(): void
{
$s3Client = new S3Client([
'credentials' => [
'key' => $this->parameterBag->get('app.aws_s3_access_key'),
'secret' => $this->parameterBag->get('app.aws_s3_access_secret'),
],
'region' => 'eu-west-2',
'version' => 'latest'
]);
$buckets = $s3Client->listBuckets()->toArray()['Buckets'];
dd($buckets);
}
#[Route('/debug/flysystem', condition: '"%kernel.environment%" === "dev"')]
public function flysystem(): void
{
$this->defaultStorage->write('example.txt', 'Example file...');
$filePaths = $this->defaultStorage->listContents('/')
->filter(fn(StorageAttributes $attributes) => $attributes->isFile())
->map(fn(StorageAttributes $attributes) => $attributes->path())
->toArray();
dd($filePaths);
}
#[Route('/debug/flysystem-s3', condition: '"%kernel.environment%" === "dev"')]
public function flysystemS3(): void
{
// Upload a file to S3
$this->s3PublicStorage->write('example1.txt', 'Example file...');
// Check that it exists
$filePaths = $this->s3PublicStorage->listContents('/')
->filter(fn(StorageAttributes $attributes) => $attributes->isFile())
->map(fn(StorageAttributes $attributes) => $attributes->path())
->toArray();
dd($filePaths);
}
}
Visit your application’s /debug/flysystem-s3
route and if all is working ok, you should see this:

And when viewing the S3 bucket’s contents on AWS, you should see example1.txt
:

Setup flysystem for tests
See here.