Rest 多部分/表单数据和表单类型验证
我正在使用和构建一个API,在这个阶段我需要实现对包含二进制数据的新实体的创建的处理 由于Base64需要增加约33%的带宽,因此遵循以Rest 多部分/表单数据和表单类型验证,rest,symfony,fosrestbundle,Rest,Symfony,Fosrestbundle,我正在使用和构建一个API,在这个阶段我需要实现对包含二进制数据的新实体的创建的处理 由于Base64需要增加约33%的带宽,因此遵循以multipart/form data的形式发送数据的方法对我们的实现来说最为实用 问题 当以多部分/form data的形式发送数据时,如何配置REST端点来处理请求中的文件并对JSON编码的实体执行验证 在发送原始JSON时,我一直在使用Symfony的formhandleRequest方法对自定义的FormType执行验证。例如: $form = $thi
multipart/form data
的形式发送数据的方法对我们的实现来说最为实用
问题
当以多部分/form data
的形式发送数据时,如何配置REST端点来处理请求中的文件并对JSON编码的实体执行验证
在发送原始JSON时,我一直在使用Symfony的formhandleRequest
方法对自定义的FormType
执行验证。例如:
$form = $this->createForm(new CommentType(), $comment, ['method' => 'POST']);
$form->handleRequest($request);
if ($form->isValid()) {
// Is valid
}
我喜欢这种方法的原因是,我可以根据操作是更新(PUT)还是新(POST)对实体的填充进行更多的控制
我知道Symfony的
请求
对象处理请求,因此以前JSON数据将是内容
变量,但现在被键入请求->参数->[form key]
和文件包中的文件(请求->文件
).似乎没有干净的方法可以在不解析原始请求的情况下检索表单数据的内容类型
如果您的API仅支持json输入,或者您可以添加自定义头(请参阅下面的注释),则可以使用此解决方案:
首先,您必须实现自己的body\u侦听器
:
然后在配置文件中:
services:
acme.api.fos.event_listener.body:
class: Acme\ApiBundle\FOS\EventListener\BodyListener
arguments:
- "@fos_rest.decoder_provider"
tags:
-
name: kernel.event_listener
event: kernel.request
method: onKernelRequest
priority: 10
最后,您只需在控制器中调用handleRequest
。例:
$form = $this->createFormBuilder()
->add('foo', 'text')
->add('file', 'file')
->getForm()
;
$form->handleRequest($request);
使用此请求格式(表单
必须替换为您的表单名称):
以下是更明确的解决方案: 复制和粘贴此代码到其他控制器是非常湿,我们喜欢干 如果我告诉您可以将此应用于每个JSON请求,而不必担心它会怎么样?我们>编写了一个事件侦听器,当标记为kernel.event_侦听器时,它将: 检查请求是否为JSON请求 如果是,请解码JSON 填充请求::$Request对象 出错时返回HTTP 400错误请求。 检查代码在! 注册此事件侦听器非常简单。只需将以下内容添加到services.xml中:
<service id="kernel.event_listener.json_request_transformer" > class="Qandidate\Common\Symfony\HttpKernel\EventListener\JsonRequestTransformerListener">
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="100" />
</service>
class=“Qandidate\Common\Symfony\HttpKernel\EventListener\JsonRequestTransformerListener”>
修改应用程序以发送JSON格式的文件内容
JSON
(包括包含文件内容的字段)JSON
发送到服务器JSON
将如下所示:
{
name: 'Foo',
phone: '123.345.678',
profile_image: 'R0lGODlhAQABAJAAAP8AAAAAACH5BAUQAAAALAAAAAABAAEAAAICBAEAOw=='
}
在放弃并考虑另一种选择,即为图像上载使用单独的端点之后。例如:
$form = $this->createForm(new CommentType(), $comment, ['method' => 'POST']);
$form->handleRequest($request);
if ($form->isValid()) {
// Is valid
}
POST/comments
POST/comments/{id}/image
我发现已经有一个包提供了各种RESTful上传过程。其中之一就是我最初希望能够在提取文件的同时将多部分/表单数据
解析为实体
多部分/表单数据发送,并且$content
的值为null@Malachi您可以修改此条件以检查api uri(例如/api/),例如,OP使用的不是FOSRestBundle,它提供了这样一种功能,我宁愿避免使用base64,因为所需的数据开销约为33%。您可以使用不同的编码。使用此方法,此讨论可能很有用(请参阅所有注释),表单组件不会直接处理该文件。看起来他们已经实现了自己的解析器,但没有处理绑定多个文件的atm@see当添加此代码时,它会产生一个通知:未定义的属性:VSmart\ApiBundle\Listener\BodyListener::$decoderProvider
。与提供的代码不同的是,我们不使用表单来处理请求。尽管调试器显示$decoderProvider确实存在。有什么想法吗?@roelvelhuizen您可以跳过类的扩展部分,使用完整的服务定义,而不是使用fos\u rest.body\u listener
作为父项。我将更新我的应答感谢,这在使用phpunit测试时似乎有效,但在通过高级rest客户端发送相同的请求时,正文仍然是空的。有什么想法吗?你使用哪一个客户?我创建了一个单独的问题,这个案例可能与原始答案有点不同。
{
name: 'Foo',
phone: '123.345.678',
profile_image: 'R0lGODlhAQABAJAAAP8AAAAAACH5BAUQAAAALAAAAAABAAEAAAICBAEAOw=='
}