PHPackages                             tiloweb/uploaded-file-type-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. tiloweb/uploaded-file-type-bundle

ActiveSymfony-bundle[File &amp; Storage](/categories/file-storage)

tiloweb/uploaded-file-type-bundle
=================================

A Symfony bundle that handles file uploads via forms and stores the URL automatically using Flysystem

v2.0.0(4mo ago)08.8k↑100%1MITPHPPHP &gt;=8.1CI passing

Since Apr 28Pushed 3mo ago2 watchersCompare

[ Source](https://github.com/Tiloweb/uploaded-file-type-bundle)[ Packagist](https://packagist.org/packages/tiloweb/uploaded-file-type-bundle)[ Docs](https://github.com/Tiloweb/uploaded-file-type-bundle)[ RSS](/packages/tiloweb-uploaded-file-type-bundle/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (8)Dependencies (12)Versions (12)Used By (0)

UploadedFileType Bundle
=======================

[](#uploadedfiletype-bundle)

[![CI](https://github.com/Tiloweb/uploaded-file-type-bundle/actions/workflows/ci.yml/badge.svg)](https://github.com/Tiloweb/uploaded-file-type-bundle/actions/workflows/ci.yml)[![Latest Stable Version](https://camo.githubusercontent.com/8363df5188dc0a01992202e2c305d6ae1845695364a5224ddae5c359e11d5ca5/68747470733a2f2f706f7365722e707567782e6f72672f74696c6f7765622f75706c6f616465642d66696c652d747970652d62756e646c652f762f737461626c65)](https://packagist.org/packages/tiloweb/uploaded-file-type-bundle)[![Total Downloads](https://camo.githubusercontent.com/1b5606dec40ab4490cf71dccbe56e38bd854e096b929ba60e1509fc78da696f6/68747470733a2f2f706f7365722e707567782e6f72672f74696c6f7765622f75706c6f616465642d66696c652d747970652d62756e646c652f646f776e6c6f616473)](https://packagist.org/packages/tiloweb/uploaded-file-type-bundle)[![License](https://camo.githubusercontent.com/b66fb369360c1c8b3db816ddb249a2d247bc37960d0a73c0cfab4b7d47066708/68747470733a2f2f706f7365722e707567782e6f72672f74696c6f7765622f75706c6f616465642d66696c652d747970652d62756e646c652f6c6963656e7365)](https://packagist.org/packages/tiloweb/uploaded-file-type-bundle)[![PHP Version](https://camo.githubusercontent.com/69bdca507c25d5f73b4f354975f39b58dc5639a7490ddbd3d1262986c337e8e2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f74696c6f7765622f75706c6f616465642d66696c652d747970652d62756e646c652e737667)](https://packagist.org/packages/tiloweb/uploaded-file-type-bundle)

A Symfony bundle that handles file uploads via forms and automatically stores the resulting URL in your entity. No more manual file handling in controllers!

✨ Features
----------

[](#-features)

- 🚀 **Zero-configuration file uploads** - Just add an option to your form field
- 📦 **Flysystem integration** - Works with any storage backend (local, S3, GCS, SFTP, etc.)
- 🔄 **Automatic URL storage** - The file URL is stored directly in your entity
- 🎯 **Custom naming strategies** - Full control over uploaded file names
- 🗑️ **Auto-cleanup** - Optionally delete previous files when uploading new ones
- 🎨 **Twig integration** - Preview uploaded images in your forms

📋 Requirements
--------------

[](#-requirements)

VersionPHPSymfony2.x≥ 8.16.4, 7.x, 8.x1.x≥ 8.16.x, 7.x📥 Installation
--------------

[](#-installation)

```
composer require tiloweb/uploaded-file-type-bundle
```

If you're not using [Symfony Flex](https://symfony.com/doc/current/setup/flex.html), add the bundle manually:

```
// config/bundles.php
return [
    // ...
    Tiloweb\UploadedFileTypeBundle\UploadedFileTypeBundle::class => ['all' => true],
];
```

⚙️ Configuration
----------------

[](#️-configuration)

### Step 1: Configure Flysystem

[](#step-1-configure-flysystem)

First, configure your filesystem adapter using the [OneupFlysystemBundle](https://github.com/1up-lab/OneupFlysystemBundle):

```
# config/packages/oneup_flysystem.yaml
oneup_flysystem:
    adapters:
        default_adapter:
            local:
                location: '%kernel.project_dir%/public/uploads'

    filesystems:
        default_filesystem:
            adapter: default_adapter
            alias: League\Flysystem\Filesystem
```

### Step 2: Configure Upload Destinations

[](#step-2-configure-upload-destinations)

```
# config/packages/uploaded_file_type.yaml
uploaded_file_type:
    configurations:
        # Default configuration for general uploads
        default:
            filesystem: 'oneup_flysystem.default_filesystem'
            base_uri: 'https://example.com/uploads'
            path: '/files'

        # Separate configuration for user avatars
        avatars:
            filesystem: 'oneup_flysystem.default_filesystem'
            base_uri: 'https://example.com/uploads'
            path: '/avatars'

        # S3 configuration for large files
        documents:
            filesystem: 'oneup_flysystem.s3_filesystem'
            base_uri: 'https://cdn.example.com'
            path: '/documents'
```

### Configuration Options

[](#configuration-options)

OptionTypeRequiredDescription`filesystem`string✅The Flysystem filesystem service ID`base_uri`string❌The base URL for accessing uploaded files`path`string❌The subdirectory path within the filesystem🚀 Usage
-------

[](#-usage)

### Basic Usage

[](#basic-usage)

Simply add the `upload` option to any `FileType` field:

```
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormBuilderInterface;

class ProductType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('name')
            ->add('image', FileType::class, [
                'upload' => 'default',  // Use the 'default' configuration
                'required' => false,
            ])
        ;
    }
}
```

That's it! When the form is submitted:

1. The file is uploaded to your configured filesystem
2. The URL is automatically stored in the `$image` property
3. No additional controller code needed!

### Custom Filename Strategy

[](#custom-filename-strategy)

Control how files are named when uploaded:

```
$builder->add('avatar', FileType::class, [
    'upload' => 'avatars',
    'filename' => function (UploadedFile $file, User $user): string {
        return sprintf(
            'user_%d_%s.%s',
            $user->getId(),
            bin2hex(random_bytes(8)),
            $file->guessClientExtension() ?? 'bin'
        );
    },
]);
```

### Disable Auto-Cleanup

[](#disable-auto-cleanup)

By default, the previous file is deleted when uploading a new one. Disable this behavior:

```
$builder->add('document', FileType::class, [
    'upload' => 'documents',
    'delete_previous' => false,  // Keep old files
]);
```

### Available Form Options

[](#available-form-options)

OptionTypeDefaultDescription`upload`string-The configuration name to use`filename`callableautoCustom filename generator`delete_previous`bool`true`Delete previous file on update📖 Complete Example
------------------

[](#-complete-example)

### Entity

[](#entity)

```
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class Product
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private string $name = '';

    #[ORM\Column(length: 500, nullable: true)]
    private ?string $image = null;

    // Getters and setters...

    public function getImage(): ?string
    {
        return $this->image;
    }

    public function setImage(?string $image): static
    {
        $this->image = $image;
        return $this;
    }
}
```

### Form

[](#form)

```
namespace App\Form;

use App\Entity\Product;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Image;

class ProductType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('name', TextType::class, [
                'label' => 'Product Name',
            ])
            ->add('image', FileType::class, [
                'upload' => 'default',
                'required' => false,
                'label' => 'Product Image',
                'constraints' => [
                    new Image([
                        'maxSize' => '5M',
                        'mimeTypes' => ['image/jpeg', 'image/png', 'image/webp'],
                    ]),
                ],
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Product::class,
        ]);
    }
}
```

### Controller

[](#controller)

```
namespace App\Controller;

use App\Entity\Product;
use App\Form\ProductType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

class ProductController extends AbstractController
{
    #[Route('/product/new', name: 'product_new')]
    public function new(Request $request, EntityManagerInterface $em): Response
    {
        $product = new Product();
        $form = $this->createForm(ProductType::class, $product);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $em->persist($product);
            $em->flush();

            // $product->getImage() now contains the URL!
            // e.g., "https://example.com/uploads/files/product_a1b2c3d4.jpg"

            return $this->redirectToRoute('product_show', ['id' => $product->getId()]);
        }

        return $this->render('product/new.html.twig', [
            'form' => $form,
        ]);
    }
}
```

### Twig Template

[](#twig-template)

The bundle provides a form theme that displays the current image:

```
{# templates/product/new.html.twig #}
{% extends 'base.html.twig' %}

{% block body %}
    New Product

    {{ form_start(form) }}
        {{ form_row(form.name) }}
        {{ form_row(form.image) }}  {# Shows current image if exists #}
        Save
    {{ form_end(form) }}
{% endblock %}
```

🎨 Customizing the Form Theme
----------------------------

[](#-customizing-the-form-theme)

Override the default template to customize how uploaded files are displayed:

```
{# templates/form/uploaded_file.html.twig #}
{% extends '@UploadedFileType/form.html.twig' %}

{% block file_widget %}
    {{ parent() }}

    {% if url is defined and url is not null %}

            {% if url matches '/\\.(jpg|jpeg|png|gif|webp)$/i' %}

            {% else %}
                View current file
            {% endif %}

    {% endif %}
{% endblock %}
```

Register your custom theme:

```
# config/packages/twig.yaml
twig:
    form_themes:
        - 'form/uploaded_file.html.twig'
```

🔧 Advanced Usage
----------------

[](#-advanced-usage)

### Using the Service Directly

[](#using-the-service-directly)

```
use Tiloweb\UploadedFileTypeBundle\UploadedFileTypeService;

class MyService
{
    public function __construct(
        private UploadedFileTypeService $uploadService,
    ) {}

    public function uploadFile(UploadedFile $file): string
    {
        return $this->uploadService->upload(
            filename: 'custom-name.pdf',
            uploadedFile: $file,
            configuration: 'documents'
        );
    }

    public function deleteFile(string $url): bool
    {
        return $this->uploadService->delete($url, 'documents');
    }

    public function fileExists(string $url): bool
    {
        return $this->uploadService->exists($url, 'documents');
    }
}
```

### Cloud Storage Examples

[](#cloud-storage-examples)

#### Amazon S3

[](#amazon-s3)

```
# config/packages/oneup_flysystem.yaml
oneup_flysystem:
    adapters:
        s3_adapter:
            awss3v3:
                client: Aws\S3\S3Client
                bucket: '%env(AWS_S3_BUCKET)%'
                prefix: uploads

    filesystems:
        s3_filesystem:
            adapter: s3_adapter

# config/packages/uploaded_file_type.yaml
uploaded_file_type:
    configurations:
        s3:
            filesystem: 'oneup_flysystem.s3_filesystem'
            base_uri: 'https://%env(AWS_S3_BUCKET)%.s3.%env(AWS_REGION)%.amazonaws.com'
            path: '/uploads'
```

#### Google Cloud Storage

[](#google-cloud-storage)

```
oneup_flysystem:
    adapters:
        gcs_adapter:
            googlecloudstorage:
                client: Google\Cloud\Storage\StorageClient
                bucket: '%env(GCS_BUCKET)%'

    filesystems:
        gcs_filesystem:
            adapter: gcs_adapter

uploaded_file_type:
    configurations:
        gcs:
            filesystem: 'oneup_flysystem.gcs_filesystem'
            base_uri: 'https://storage.googleapis.com/%env(GCS_BUCKET)%'
            path: '/uploads'
```

🧪 Testing
---------

[](#-testing)

```
# Run tests
composer test

# Run static analysis
composer phpstan

# Fix coding standards
composer cs-fix
```

🤝 Contributing
--------------

[](#-contributing)

Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

📄 License
---------

[](#-license)

This bundle is released under the [MIT License](LICENSE).

🙏 Credits
---------

[](#-credits)

- [Thibault HENRY](https://henry.pro) - Creator
- [All Contributors](https://github.com/Tiloweb/uploaded-file-type-bundle/contributors)

🔗 Links
-------

[](#-links)

- [Documentation](https://github.com/Tiloweb/uploaded-file-type-bundle)
- [Issue Tracker](https://github.com/Tiloweb/uploaded-file-type-bundle/issues)
- [Packagist](https://packagist.org/packages/tiloweb/uploaded-file-type-bundle)
- [OneupFlysystemBundle](https://github.com/1up-lab/OneupFlysystemBundle)
- [Flysystem](https://flysystem.thephpleague.com/)

###  Health Score

49

—

FairBetter than 95% of packages

Maintenance79

Regular maintenance activity

Popularity25

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity67

Established project with proven stability

 Bus Factor1

Top contributor holds 90% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~170 days

Recently: every ~281 days

Total

11

Last Release

143d ago

Major Versions

v0.5 → v1.0.02022-11-27

v1.0.3 → v2.0.02025-12-27

PHP version history (5 changes)0.1PHP ^7.1.3||^8.0

0.2.1PHP ^7.1.3

v0.4PHP ^7.1.3|^8.0

v1.0.1PHP ^7.4||^8.1.0

v1.0.3PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/23775963348d3094c5ad98844104ffd8bc723606291a91fbb7fc4a2b79e4dc0a?d=identicon)[Tiloweb](/maintainers/Tiloweb)

---

Top Contributors

[![Tilotiti](https://avatars.githubusercontent.com/u/932380?v=4)](https://github.com/Tilotiti "Tilotiti (18 commits)")[![camille-guerber](https://avatars.githubusercontent.com/u/17534749?v=4)](https://github.com/camille-guerber "camille-guerber (2 commits)")

---

Tags

symfonybundleFlysystems3awsfilestorageuploadform

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/tiloweb-uploaded-file-type-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/tiloweb-uploaded-file-type-bundle/health.svg)](https://phpackages.com/packages/tiloweb-uploaded-file-type-bundle)
```

###  Alternatives

[league/flysystem-aws-s3-v3

AWS S3 filesystem adapter for Flysystem.

1.6k263.6M790](/packages/league-flysystem-aws-s3-v3)[league/flysystem-async-aws-s3

AsyncAws S3 filesystem adapter for Flysystem.

2610.5M31](/packages/league-flysystem-async-aws-s3)[artgris/filemanager-bundle

FileManager is a simple Multilingual File Manager Bundle for Symfony

182420.8k9](/packages/artgris-filemanager-bundle)[presta/image-bundle

PrestaImageBundle is a Symfony bundle providing tools to resize uploaded and remote images before sending them through a classic form.

24155.9k](/packages/presta-image-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
