VichUploaderBundle – How to Fix: Cannot Overwrite / Update Uploaded File

this picture of george osbourne has no relevance to this post. i hope it cheered you up.This one stumped me a few days back, and I have had the Chrome tab open ever since to remind myself of how to fix this in future.

The problem: VichUploaderBundle will let you upload a file, but when you go back to the form to edit / update / over-write that file by uploading a new one, it doesn’t upload the new file.

The solution: I cannot take credit for this, as the solution was found by digging around in the github closed issues list for the project, where JMather had posted his working fix.

For those who cannot be bothered to click any of the links I have so helpfully provided, read on.

Make sure you have something like this in your config.yml:

    db_driver: orm
    gaufrette: false
    twig: true
            delete_on_remove: true
            delete_on_update: true
            inject_on_load: true
            upload_destination: /some/path/to/uploads
            namer: vich_user_upload_file_naming_service

I’m not using Gaufrette for a couple of reasons I won’t go in too. And also, I’m saving the given uploads outside of my Symfony install for security.

The key line is: delete_on_update: true

The other important thing here is you have to have some way of telling your ORM that the file has been updated. This is not immediately obvious, and isn’t documented at all.

So the solution seems to be:

1. Make sure you have at least an updatedAt field in the entity you are uploading too. I would normally have a createdAt and updatedAt field, and use LifecycleCallbacks to update these fields for me on prePersist and preUpdate. This isn’t well documented either in my opinion, so if you are unsure how to use them, please read my post on Lifecycle Callbacks.

2. Then update the method you are using to save the uploaded file to include an updating of the updatedAt property inside your entity. Sounds confusing, so it’s better to explain it with a code snippet:

    public function setUploadedFile($uploadedFile)
        $this->uploadedFile = $uploadedFile;

        if ($uploadedFile instanceof UploadedFile) {
            $this->setUpdatedAt(new \DateTime());

All we are saying here is to set the updatedAt time to now if this is an uploaded file.

This then tells your ORM that the file is new – in a very round the houses kind of way – and correctly uploads the new file. And because we used delete_on_update: true, the old file is deleted so no need to worry about that.

Again, check out the github link if this still doesn’t make sense.

Thanks to Chrysweel for raising this issue, and to JMather for solving it.