问题
First, since English is not my native tongue, please excuse my mistakes.
I'm trying to develop my first project through Symfony2. However I got stuck with file uploads. So I've installed VichUploaderBundle which provide exactly what I need to manage: all kind of uploaded Media (mainly images).
Why do I need to upload an image? I have user on my project, and they can edit their profile. So, I have an entity ProfilePicture which should manage the upload, thanks to VichUploaderBundle. It works perfectly when the form is send using the submit button or using ajax.
However, to improve the user's experience, I've also added a jQuery plugin (Cropit). Cropit give a base64 of the cropped picture. I send the whole using ajax.
And know... I struggle. I've been searching everywhere on internet to find someone with a beginning of an idea, I've read all the docs, trying to find another way to do what I'm trying to do.
Here is my actual "test" code:
$base64 = $request->request->get('base64');
preg_match('/data:([^;]*);base64,(.*)/', $base64, $matches);
$data = base64_decode($matches[2]);
$ui = uniqid().'.png';
$file = 'images/profile_pictures/'. $ui;
file_put_contents($file, $data);
$picture = new File($file);
$profile->getPicture()->setImageFile($picture);
This allow me to save the cropped picture in the wanted directory. However, that's not really what I'd like. In fact, I'm just trying to find a way to transform my base64 content to what would have been present in the $profile->getPicture()->setImageFile() if I had just sent a picture. I'm vague and I'm sorry. It's the first time I have to create an upload system.
I thought there might be a way to avoid sending a base64. But what can we do with this kind of data? Can we use jQuery to decode it and transform my form's just to send the form as it would be if I just select my picture and want to save the whole of it?
How do you manage that in your project? Is there any other bundle better than this one? I've been looking for, with no success. SonataMediaBundle seems to big for my need, and I found no way to save my cropped picture with it too.
I found someone who wanted to manage it on the Git of VichUploaderBundle. However, his issue was closed before a better answer was given... https://github.com/dustin10/VichUploaderBundle/issues/223
Thanks in advance for you help!
回答1:
The issue was closed because it doesn't fit in the bundle' scope. VichUploaderBundle basically maps UploadedFile
objects to entities through forms, that's all.
The keywords for your problem being "UploadedFile"
and "forms".
If you have to send your file as base64-encoded strings, raw bytes, ... then you'll have to convert it to an UploadedFile
in order to make it work with VichUploaderBundle. I guess a DataTransformer could do the trick. It could decode the base64-encoded string and store it in a temporary file, which could be used to build an UploadedFile object.
回答2:
I'd like to share my current solution.
I need to upload images encoded in base64. These images are generated using the cropper.js
lib and posted to a specific endpoint.
I've used a DataTransformerInterface
to build an UploadedFile
object like K-Phoen suggested.
I'd like to point out some differences from the canonical usage of the bundle.
Use TextType
instead of VichFileType
(otherwise validation will fail).
Use a data trasformer to decode the image an save it temporary (thank you for the hint K-Phoen).
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('file', TextType::class, ['required' => true]);
$builder->get('file')->addModelTransformer(new FileToBase64Transformer());
}
My FileToBase64Trasformer
:
class FileToBase64Transformer implements DataTransformerInterface
{
public function transform($value)
{
}
public function reverseTransform($value)
{
$tmpFilePath = tempnam(sys_get_temp_dir(), 'allegato_');
$tmp = fopen($tmpFilePath, 'wb+');
$matches = [];
preg_match('/^data:([\w-]+\/[\w-]+);base64,(.+)$/', $value, $matches);
$size = fwrite($tmp, base64_decode($matches[2]));
fclose($tmp);
return new UploadedFile($tmpFilePath, 'originalName', $matches[1], $size, 0, true);
}
}
Pay attention to the parameters of UploadedFile
's constructor:
- The 3rd parameter is the mime type of the file
- The 4th param is the error code (
0
means no errors at all) - The 5th param does the trick. Internally
UploadedFile
will callis_uploaded_file
function, wich will fail (the file is created by decoding a base64 string, not uploaded) raising an unknown error. If you understand and accept the risk, set this parameter totrue
to avoid it.
来源:https://stackoverflow.com/questions/31496318/vichuploaderbundle-cropit-pass-base64-to-a-file-instance