base64 image to image file with Symfony and VichUploader
An attempt of solution is to transform first the base64 file into a symfony uploadedFile.
- You define this service
<?php
namespace App\Utils;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class UploadedBase64File extends UploadedFile
{
public function __construct(string $base64String, string $originalName)
{
$filePath = tempnam(sys_get_temp_dir(), 'UploadedFile');
$data = base64_decode($base64String);
file_put_contents($filePath, $data);
$error = null;
$mimeType = null;
$test = true;
parent::__construct($filePath, $originalName, $mimeType, $error, $test);
}
}
And then this another service to extract the pur base64 string image
<?php
namespace App\Utils;
class Base64FileExtractor
{
public function extractBase64String(string $base64Content)
{
$data = explode( ';base64,', $base64Content);
return $data[1];
}
}
- And in your 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;
use App\Utils\Base64FileExtractor;
class CoreController extends AbstractController
{
/**
* @Route("/images", methods={"POST"}, name="app_add_image")
*/
public function addImage(Request $request, Base64FileExtractor $base64FileExtractor)
{
//...
if($form->isSubmitted() && $form->isValid()) {
$base64Image = $request->request->get('base64Image');
$base64Image = $base64FileExtractor->extractBase64String($base64Image);
$imageFile = new UploadedBase64File($base64Image, "blabla");
$program->setImage($imageFile);
//...
// Do thing you want to do
}
// Do thing you want to do
}
}
- The method setImage in your Program entity can be something like
/**
* @param null|File $image
* @return Program
*/
public function setImage(?File $image): Program
{
$this->image = $image;
if($this->image instanceof UploadedFile) {
$this->updatedAt = new \DateTime('now');
}
return $this;
}
If you want to validate the image, you should set it directly after handling form and the validation will be done habitually. I hope this idea can help you.
Dirk J. Faber
Updated on June 05, 2022Comments
-
Dirk J. Faber almost 2 years
In symfony, I have an entity
Program
, which has the attributeimage
. Uploading images, naming them and putting them in the right directory is done with theVichUploaderBundle
. The entity looks like this://... /** * NOTE: This is not a mapped field of entity metadata, just a simple property. * * @Assert\Image( * maxSize="5M", * mimeTypesMessage="The file you tried to upload is not a recognized image file" * ) * @Vich\UploadableField(mapping="program_image", fileNameProperty="imageName") * * @var File */ private $image; /** * @ORM\Column(type="string", length=191, nullable=true) */ private $imageName; //...
Now I wish for images to be processed before they are uploaded, which I have done with some JS that returns a base64 string. I put this string in a hidden input field,
base64Image
. I then retrieve this string in my controller and try to make it into an image that I can save to my entity like so:if ($form->isSubmitted() && $form->isValid()) { $program = $form->getData(); $base64String = $request->request->get('base64Image'); $decodedImageString = base64_decode($base64String); $program->setImage($decodedImageString); //etc.....
The program occurs with the last line.
$decodedImageString
is actually another string that first needs to be created into a file. I have looked intofile_put_contents
to create a file as describer here, but with no luck.The filename cannot be empty
Is the error I receive. Also I don't know if this would work with the
VichUploaderBundle
and perhaps the answer in that question is also outdated. Any suggestions on what I could do?Edit: Got the converting and uploading working with the following code:
define('UPLOAD_DIR', 'images/'); $img = $request->request->get('base64Image'); $img = str_replace('data:image/jpeg;base64,', '', $img); $img = str_replace(' ', '+', $img); $data = base64_decode($img); $file = UPLOAD_DIR . uniqid() . '.jpeg'; $success = file_put_contents($file, $data); print $success ? $file : 'Unable to save the file.';
Now I just need to load the VichUploaderBundle config somehow, or maybe not use that altogether perhaps.
-
William Bridge about 5 yearsI posted an answer here in this topic converting-any-base64-file-to-a-file-and-moving-to-the-targeted-path-in-php-symfony. I hope this can give you an idea to how to manage it with vichuploaderbundle.
-
William Bridge about 5 yearsAnd then you also have this answer through this topic convert-base64-string-to-an-image-file. This can help you extract pur base64 image and you combine with my answer above to manage it with vichuploaderbundle.
-
Dirk J. Faber about 5 years@williambridge, I tried everything you wrote down. I still have a problem when I try to save the image using
$program->saveImage()
. The temporary file that is created withtempnam()
won't be recognised as file, but as a string. I tried changing the extensions to .jpeg, but that didn't work either.
-
-
Dirk J. Faber about 5 yearsI get a bunch of errors when using this. Firstly the method uuid1 is not recognized. but even when I manually give the file a name, I get an error the ' ul_path' is not defined.
-
Dirk J. Faber about 5 yearsAppreciate it. I managed with some similar method (see the edit). Now I just need to figure out how to use the VichUploaderBundle with this.
-
Dirk J. Faber about 5 yearsVery helpful indeed. A crucial part turns out to be
$test = true;
when using theUploadedFile
. I am not completely where I want to be yet, but this is getting me on the right track.