使用 Symfony 和 VichUploader 将 base64 图像转换为图像文件
base64 image to image file with Symfony and VichUploader
在 symfony 中,我有一个实体 Program
,它具有属性 image
。使用 VichUploaderBundle
完成上传图像、命名它们并将它们放在正确的目录中。实体看起来像这样:
//...
/**
* 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;
//...
现在我希望在上传图片之前对其进行处理,我已经用一些 returns base64 字符串的 JS 完成了。我把这个字符串放在一个隐藏的输入字段中,base64Image
。然后我在我的控制器中检索这个字符串并尝试将它变成一个图像,我可以像这样保存到我的实体:
if ($form->isSubmitted() && $form->isValid()) {
$program = $form->getData();
$base64String = $request->request->get('base64Image');
$decodedImageString = base64_decode($base64String);
$program->setImage($decodedImageString);
//etc.....
程序出现在最后一行。 $decodedImageString
实际上是另一个字符串,首先需要将其创建到文件中。我研究了 file_put_contents
以创建描述符 here 的文件,但没有成功。
The filename cannot be empty
是我收到的错误。另外我不知道这是否适用于 VichUploaderBundle
并且也许该问题的答案也已过时。关于我可以做什么的任何建议?
编辑:
使用以下代码进行转换和上传:
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.';
现在我只需要以某种方式加载 VichUploaderBundle 配置,或者可能完全不使用它。
您正在尝试将整个图像存储到 setImage
。
然而,您在这里需要的是一个字符串值。
我就是这样做的。
$ext='.png';
$fileName='file_name'.$ext;
$base64=str_replace('data:image/png;base64,', '', $base64);
$file=fopen('path_to_upload_dir'.$fileName, 'wb');
fwrite($file, base64_decode($base64));
fclose($file);
$program->setImage($fileName);
解决方案的尝试是首先将 base64 文件转换为 symfony 上传的文件。
- 您定义此服务
<?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);
}
}
然后这是另一个提取 pur base64 字符串图像的服务
<?php
namespace App\Utils;
class Base64FileExtractor
{
public function extractBase64String(string $base64Content)
{
$data = explode( ';base64,', $base64Content);
return $data[1];
}
}
- 并且在您的控制器中,您可以执行以下操作:
<?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
}
}
- 程序实体中的方法 setImage 可以类似于
/**
* @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;
}
如果要验证图片,在处理完表单后直接设置,习惯性验证。
我希望这个想法可以帮助你。
在 symfony 中,我有一个实体 Program
,它具有属性 image
。使用 VichUploaderBundle
完成上传图像、命名它们并将它们放在正确的目录中。实体看起来像这样:
//...
/**
* 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;
//...
现在我希望在上传图片之前对其进行处理,我已经用一些 returns base64 字符串的 JS 完成了。我把这个字符串放在一个隐藏的输入字段中,base64Image
。然后我在我的控制器中检索这个字符串并尝试将它变成一个图像,我可以像这样保存到我的实体:
if ($form->isSubmitted() && $form->isValid()) {
$program = $form->getData();
$base64String = $request->request->get('base64Image');
$decodedImageString = base64_decode($base64String);
$program->setImage($decodedImageString);
//etc.....
程序出现在最后一行。 $decodedImageString
实际上是另一个字符串,首先需要将其创建到文件中。我研究了 file_put_contents
以创建描述符 here 的文件,但没有成功。
The filename cannot be empty
是我收到的错误。另外我不知道这是否适用于 VichUploaderBundle
并且也许该问题的答案也已过时。关于我可以做什么的任何建议?
编辑: 使用以下代码进行转换和上传:
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.';
现在我只需要以某种方式加载 VichUploaderBundle 配置,或者可能完全不使用它。
您正在尝试将整个图像存储到 setImage
。
然而,您在这里需要的是一个字符串值。
我就是这样做的。
$ext='.png';
$fileName='file_name'.$ext;
$base64=str_replace('data:image/png;base64,', '', $base64);
$file=fopen('path_to_upload_dir'.$fileName, 'wb');
fwrite($file, base64_decode($base64));
fclose($file);
$program->setImage($fileName);
解决方案的尝试是首先将 base64 文件转换为 symfony 上传的文件。
- 您定义此服务
<?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);
}
}
然后这是另一个提取 pur base64 字符串图像的服务
<?php
namespace App\Utils;
class Base64FileExtractor
{
public function extractBase64String(string $base64Content)
{
$data = explode( ';base64,', $base64Content);
return $data[1];
}
}
- 并且在您的控制器中,您可以执行以下操作:
<?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
}
}
- 程序实体中的方法 setImage 可以类似于
/**
* @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;
}
如果要验证图片,在处理完表单后直接设置,习惯性验证。 我希望这个想法可以帮助你。