更新时间:2023-11-19 21:07:40
我一直在寻找一个关于完全相同的问题的解决方案。下面是我做的。
I have been looking for a solution about the exact same problem. Here is what I did.
首先让我解释一下我的约束。我希望我的API是充满JSON,并采取HTTP协议的功率(头,方法等)。我选择使用:
First let me explain my constraints. I wanted my API to be full JSON and to take power of the HTTP protocol (headers, methods, etc.). I chose to use:
第一个解决方案设想:BASE64
我首先想到的,因为我在想JSON每次,是EN code以base64所有传入的图片,我的API里面,并将其储存然后去code他们。
My first thought, because I was thinking JSON everytime, was to encode all the incoming images in base64, then decode them inside my API and store them.
这种解决方案的优点是,可以与其他数据一起传送的图像。例如在一个API调用上传整个用户的个人资料。不过,我看到,在Base64编码的图像让他们其初始大小的33%的速度增长。我送3的图像后不希望我的用户成为了移动数据流量。
The advantage with this solution is that you can pass images along with other data. For instance upload a whole user's profile in one API call. But I read that encoding images in base64 make them grow by 33% of their initial size. I did not wanted my users to be out of mobile data after sending 3 images.
二的解决方案设想:形式
然后我想用上述形式。但我不知道怎么我的客户会同时发送JSON数据(例如 {姓氏:利兹}
)和图像数据(例如图像/ PNG
之一)。我知道,你可以处理一个内容类型:多重/ form-data的
但仅此而已。
Then I thought using forms as described above. But I did not know how my clients could send both JSON data (for instance {"last_name":"Litz"}
) and image data (for instance image/png
one). I know that you can deal with an Content-Type: multipart/form-data
but nothing more.
另外,我没有使用形式从一开始我的API和我想它是在我所有的code均匀。 [微型编辑:HOHO,这是我刚刚发现,这里]
Plus I was not using forms in my API since the beginning and I wanted it to be uniform in all my code. [mini-edit: hoho, something I just discovered, here]
第三和最后的解决方案:使用HTTP ..
然后,一到晚上,启示。我使用内容类型:应用程序/ JSON
为发送JSON数据。为什么不使用图像/ *
发送图像?很容易,我搜索了天,这个思想来之前。这是我做的(简化code)。让我们假设用户在调用 PUT / API / ME /图片
与内容类型:图像/ *
Then, one night, the revelation. I'm using Content-Type: application/json
for send JSON data. Why not use image/*
to send images? So easy that I searched for days before coming with this idea. This is how I did it (simplified code). Let suppose that the user is calling PUT /api/me/image
with a Content-Type: image/*
UserController中:: getUserImageAction(请求$要求) - 捕请求
UserController::getUserImageAction(Request $request) - Catching the Request
// get the service to handle the image
$service = $this->get('service.user_image');
$content = $request->getContent();
$userImage = $service->updateUserImage($user, $content);
// get the response from FOSRestBundle::View
$response = $this->view()->getResponse();
$response->setContent($content);
$response->headers->set('Content-Type', $userImage->getMimeType());
return $response;
UserImageService :: updateUserImage($用户,$内容) - 业务逻辑(我把这里的一切是simplier阅读)
UserImageService::updateUserImage($user, $content) - Business Logic (I put everything here to be simplier to read)
// Create a temporary file on the disk
// the temp file will be delete at the end of the script
// see http://www.php.net/manual/en/function.tmpfile.php
$file = tmpfile();
if ($file === false)
throw new \Exception('File can not be opened.');
// Put content in this file
$path = stream_get_meta_data($file)['uri'];
file_put_contents($path, $content);
// the UploadedFile of the user image
// referencing the temp file (used for validation only)
$uploadedFile = new UploadedFile($path, $path, null, null, null, true);
// the UserImage to return
$userImage = $user->getUserImage();
if (is_null($userImage))
{
$userImage = new UserImage();
$userImage->setOwner($user);
// auto persist with my configuration
// plus generation of a unique ID that allows
// me to retrieve the image at anytime
$userImage->setKey(/*random string*/);
}
// fill the UserImage properties
$userImage->setImage($uploadedFile);
$userImage->setMimeType($uploadedFile->getMimeType());
/** @var ConstraintViolationInterface $validationError */
if (count($this->getValidator()->validate($userImage)) > 0)
throw new \Exception('Validation');
// if no error we can write the file definitively
// [KnpGaufretteBundle code to store on disk]
// [use the UserImage::key to store]
$this->getEntityManager()->flush();
return $userImage;