Uploading Images in Symfony: A Developer’s Journey

Lubna Altungi
3 min readJan 8, 2024

--

Embarking on the journey of adding image uploads to a Symfony form, without using specialized bundles like Dropzone, is a key aspect of web development. If you’ve got a Symfony app set up locally with an existing form, let’s walk through the essential steps to make the process smooth and straightforward.

File Validation

To ensure the uploaded file is indeed an image (jpeg, png, jpg), server-side validation is essential. Utilize constraints such as:

Cd project/src/Form/YourFormType.php

use Symfony\Component\Validator\Constraints\File;
use Symfony\Component\Form\Extension\Core\Type\FileType;

//..

->add('imageA', FileType::class, [
'mapped' => false,
'constraints' => [
new File([
'maxSize' => '3000k',
'mimeTypes' => [
'image/*',
],
'mimeTypesMessage' => 'Veuillez télécharger une image valide',
])
],
])
  • ‘maxSize’ => ‘3000k’ limits the file size to 3 MB.
  • ‘mimeTypes’ => [‘image/*’] allows only files of image type.

Image Upload Service:

You need to create a service so you can use it everytime you need to create an image field in your form to include some functions like:

· Changing the Name: Assigning a new name to the file for security or organizational reasons.

· Choosing the Directory: Selecting the secure storage directory for images, with a URL to public resources.

Cd project/src/Service/FileUploader.php

public function upload(UploadedFile $file): string
{
$newFileName = md5(uniqid()) . '.' . $file->guessExtension();
$file->move($this->targetDirectory, $newFileName);

return $newFileName;
}

In your controller, handle the uploaded image:

Cd project/src/Controller/AccountController.php

$uploadedFile = $form->get('avatar')->getData();
if ($uploadedFile) {
$newFileName = $fileUploader->upload($uploadedFile);
$account->setAvatar($newFileName);
}

PS : In Twig, use the getAvatarUrl method to retrieve the ‘avatar’ value. Note that the returned parameter is ‘avatarUrl’ due to path modifications.

Cd project/src/Entity/Account.php

public function getAvatarUrl(): ?string
{
if (!$this->avatar) {
return null;
}
if (strpos($this->avatar, '/') !== false) {
return $this->avatar;
}
return sprintf('/uploads/avatar/img/%s', $this->avatar);
}

Preview Image in Form:

Let’s add some js to enhance user experience providing a preview of the uploaded image directly in the form:

Cd project/templates/account/index.html.twig

{{ form_row(account_form.avatar, {
label: 'Photo :',
mapped: false,
attr: {
onchange: "previewAvatar(this)"
}
}) }}

<script>
function previewAvatar(input) {
var preview = document.getElementById('avatarPreview');
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
preview.src = e.target.result;
};
reader.readAsDataURL(input.files[0]);
}
}
</script>

EasyAdmin field Configuration:

If you use EasyAdmin, you can configure image upload using ImageField:

    public function configureFields(string $pageName): iterable
{
return [
ImageField::new(avatar, 'Avatar')
->setUploadDir('public/uploads/avatar/img)
->setBasePath('uploads/avatar/img')
->setUploadedFileNamePattern('[slug]-[timestamp].[extension]'),
];
}

LiipImagineBundle:

Enhance Symfony’s capabilities with LiipImagineBundle, providing tools for image resizing, cropping, and applying filters. Begin by installing the bundle:

PS: You must enable the GD extension in your php.ini file.

Execute the following command to download the latest stable version of this bundle:

composer require liip/imagine-bundle

Configure the bundle by specifying thumbnail creation modes in the liip_imagine.yaml file:

Cd project/config/packages/liip_imagine.yaml

squared_thumbnail_small:
filters:
thumbnail:
size: [300, 300]
mode: inset
position: center
allow_upscale: true

squared_thumbnail_medium:
filters:
thumbnail:
size: [400, 400]
mode: inset
position: center
allow_upscale: true
squared_thumbnail_grand:
filters:
thumbnail:
size: [700, 700]
mode: inset
position: center
allow_upscale: true

Production mode:

In production mode, configuration adjustments are often necessary, particularly with regard to permissions. For my Apache2 setup, I found it necessary to customize the configuration, specifically for the directory containing thumbnail images. The configuration in liip_imagine.yaml looks like this:

    loaders:
default:
filesystem:
data_root:
- '%kernel.project_dir%/public'

It’s crucial to ensure proper permissions for the thumbnail cache directory. Execute the following commands:

mkdir -p public/media/cache
chmod -R 775 public/media/cache
chown -R www-data:www-data public/media/cache

These adjustments are vital for a seamless production environment, where setting permissions correctly is essential for both security and optimal functionality.

By following these steps, you can seamlessly integrate image uploads into your Symfony application. Symfony’s EasyAdmin and LiipImagineBundle, combined with effective upload processes, empower developers to create visually appealing and dynamic web applications. This comprehensive guide ensures proper validation, security, and efficient handling of images within the Symfony framework.

--

--