Skip to content

Instantly share code, notes, and snippets.

@reanim8ed
Created September 21, 2020 20:51
Show Gist options
  • Save reanim8ed/f67053e688140cbde76575297e773e12 to your computer and use it in GitHub Desktop.
Save reanim8ed/f67053e688140cbde76575297e773e12 to your computer and use it in GitHub Desktop.
[Converting base64 file and moving to path] #symfony #upload #vichupload
  • composer require vich/uploader-bundle
  • In the config/services.yaml, add this configuration (it's just an example)
	# config/services.yaml
	parameters:
		app.path.images: /uploads/images
  • don't forget to create uploads directory inside public directory and images directory inside uploads directory
  • And you configure the file config/packages/vich_uploader.yaml like
# config/packages/vich_uploader.yaml
vich_uploader:
    db_driver: orm

    mappings:
        object_image:
            uri_prefix: '%app.path.images%'
            upload_destination:   '%kernel.project_dir%/public%app.path.images%'
            namer: Vich\UploaderBundle\Naming\UniqidNamer
            delete_on_remove: true
            delete_on_update: true
  • create an image entity (with validation assert) like
   <?php

    namespace App\Entity;

    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\HttpFoundation\File\File;
    use Symfony\Component\HttpFoundation\File\UploadedFile;
    use Symfony\Component\Validator\Constraints as Assert;
    use Vich\UploaderBundle\Mapping\Annotation as Vich;

    /**
     * @ORM\Entity(repositoryClass="App\Repository\ImageRepository")
     * @Vich\Uploadable()
     * @ORM\Table(name="image")
     */
    class Image
    {
        /**
         * @ORM\Id()
         * @ORM\GeneratedValue()
         * @ORM\Column(type="integer")
         */
        private $id;

        /**
         * @var File|null
         * @Assert\NotBlank(message="Please upload a file.")
         * @Assert\File(
         *     maxSize = "1M",
         *     maxSizeMessage = "Maximum size allowed : {{ limit }} {{ suffix }}.",
         *     mimeTypes = {"image/png", "image/jpg", "image/jpeg"},
         *     mimeTypesMessage = "Allowed formats : png, jpg, jpeg."
         * )
         * @Vich\UploadableField(mapping="object_image", fileNameProperty="imageName")
         */
        private $imageFile;

        /**
         * @var string|null
         *
         * @ORM\Column(type="string", length=255)
         */
        private $imageName;

        /**
         * @var \DateTime
         * @ORM\Column(type="datetime")
         *
         */
        private $createdAt;

        /**
         * @var \DateTime
         * @ORM\Column(type="datetime")
         */
        private $updatedAt;

        public function __construct()
        {
            $this->createdAt = new \DateTime('now');
        }

        public function getId(): ?int
        {
            return $this->id;
        }

        /**
         * @return \DateTime
         */
        public function getCreatedAt(): \DateTime
        {
            return $this->createdAt;
        }

        /**
         * @param \DateTime $createdAt
         * @return Image
         */
        public function setCreatedAt(\DateTime $createdAt)
        {
            $this->createdAt = $createdAt;
            return $this;
        }

        /**
         * @return \DateTime
         */
        public function getUpdatedAt(): \DateTime
        {
            return $this->updatedAt;
        }

        /**
         * @param \DateTime $updatedAt
         * @return Image
         */
        public function setUpdatedAt(\DateTime $updatedAt)
        {
            $this->updatedAt = $updatedAt;

            return $this;
        }

        /**
         * @return null|File
         */
        public function getImageFile(): ?File
        {
            return $this->imageFile;
        }

        /**
         * @param null|File $imageFile
         * @return Image
         */
        public function setImageFile(?File $imageFile): Image
        {
            $this->imageFile = $imageFile;

            if($this->imageFile instanceof UploadedFile) {
                $this->updatedAt = new \DateTime('now');
            }

            return $this;
        }

        /**
         * @return null|string
         */
        public function getImageName(): ?string
        {
            return $this->imageName;
        }

        /**
         * @param null|string $imageName
         * @return Image
         */
        public function setImageName(?string $imageName): Image
        {
            $this->imageName = $imageName;
            return $this;
        }

    }
  • create a form image entity like
 <?php

    namespace App\Form;

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

    class ImageType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('imageFile', FileType::class)
            ;
        }

        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'data_class' => Image::class
            ]);
        }
    }
  • you create an UploadedBase64File service (in Utils directory that you will create ) like
  <?php

    namespace App\Utils;

    use Symfony\Component\HttpFoundation\File\UploadedFile;

    class UploadedBase64File extends UploadedFile
    {

        public function __construct(string $base64Content, string $originalName)
        {
            $filePath = tempnam(sys_get_temp_dir(), 'UploadedFile');
            $data = base64_decode($this->getBase64String($base64Content));
            file_put_contents($filePath, $data);
            $error = null;
            $mimeType = null;
            $test = true;

            parent::__construct($filePath, $originalName, $mimeType, $error, $test);
        }

        private function getBase64String(string $base64Content)
        {

            $data = explode(';base64,', $base64Content);
            return $data[1];

        }

    }
  • Finally in a controller, you can do something like
 <?php

    namespace App\Controller\Api;

    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\Routing\Annotation\Route;
    use App\Utils\UploadedBase64File;

    class CoreController extends AbstractController
    {
       /**
         * @Route("/api/images", methods={"POST"}, name="api_add_image")
         */
         public function addImage(Request $request) 
         {
             $data = json_decode($request->getContent(), true);
             if($data === null
                || !is_array($data)
                || count($data) !== 1
                || !isset($data['image']['name'], $data['image']['value'])
                || count($data['image']) !== 2
             ) {
                // Throw invalid format request for image
             }

             $imageFile = new UploadedBase64File($data['image']['value'], $data['image']['name']);
             $image = new Image();
             $form = $this->createForm(ImageType::class, $image, ['csrf_protection' => false]);
             $form->submit(['imageFile' => $imageFile]);  

             if(!($form->isSubmitted() && $form->isValid())) {
                 // Send json form error
             }

             // Persist, do thing you want to do and send json response 
         }
   }
  • And if you want to test in postman, you can do something like
{
	"image": {
		"name": "originalfilename.png",
		"value": "base64 content"
	}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment