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"
}
}