简体   繁体   English

多部分请求时Fosrestbundle正空

[英]Fosrestbundle body empty when multipart request

In the code bellow I expect the $request->getContents() to get the body content of the HTTP request. 在下面的代码中,我希望$request->getContents()获取HTTP请求的正文内容。 When sending non multipart request this works as expected though when using multipart requests the $body variable remains empty. 当发送非多部分请求时,这可以按预期工作,但是当使用多部分请求时, $body变量保持为空。

public function postDebugAction(Request $request) {
    $body = $request->getContent();

    if (empty($body)) {
        throw new \Exception('Body empty.');
    }


    return $this->view(array(), 201);
}

After reading this question and answer I added a body listener aswell. 在阅读了这个问题和答案之后,我还添加了一个身体监听器。

<?php

namespace VSmart\ApiBundle\Listener;

use FOS\RestBundle\EventListener\BodyListener as BaseBodyListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use FOS\RestBundle\Decoder\DecoderProviderInterface;

class BodyListener extends BaseBodyListener {

    /**
     * @var DecoderProviderInterface
     */
    private $decoderProvider;

    /**
     * @param DecoderProviderInterface $decoderProvider Provider for fetching decoders
     */
    public function __construct(DecoderProviderInterface $decoderProvider) {
        $this->decoderProvider = $decoderProvider;
    }

    /**
     * {@inheritdoc}
     */
    public function onKernelRequest(GetResponseEvent $event) {
        $request = $event->getRequest();

        if (strpos($request->headers->get('Content-Type'), 'multipart/form-data') !== 0) {
            return;
        }

        $format = 'json';

        if (!$this->decoderProvider->supports($format)) {
            return;
        }

        $decoder = $this->decoderProvider->getDecoder($format);
        $iterator = $request->request->getIterator();
        $request->request->set($iterator->key(), $decoder->decode($iterator->current(), $format));
    }

}

According to my PHPUnit test this was working though when using Postman and Advanced Rest Client to simulate the request the body seems to be empty again. 根据我的PHPUnit测试,当使用PostmanAdvanced Rest Client模拟请求时,身体似乎再次为空。 I double checked this to run both the simulate requests as PHPUnit with the debugger. 我仔细检查了这个以使用调试器将模拟请求作为PHPUnit运行。 Result is that, indeed, the body is empty when simulated via a Rest client and not empty when ran through PHPUnit. 实际上,当通过Rest客户端模拟时,正文是空的,而当通过PHPUnit运行时,正文是空的。

The test case I used: 我使用的测试用例:

POST url: POST网址:

http://localhost/EntisServer/web/app_dev.php/api2/debug

Headers: 头:

Authorization: Bearer ZGYzYjY1YzY4MGY3YWM3OTFhYTI4Njk3ZmI0NmNmOWZmMjg5MDFkYzJmOWZkOWE4ZTkyYTRmMGM4NTE1MWM0Nw
Content-Type: multipart/form-data; boundary=-----XXXXX

Content: 内容:

-----XXXXX
Content-Disposition: form-data; name="json"
Content-Type: application/json; charset=utf-8

{
    "blabla": 11
}

-----XXXXX
Content-Disposition: form-data; name="q_3101"; filename="image.jpg"
Content-Type: image/jpeg

contents of a file...

-----XXXXX--

UPDATE I was uncertain whether I stepped through the debugger without using the BodyListener . 更新我不确定是否在不使用BodyListener情况下逐步完成调试器。 When I did the result is exactly the same. 当我这样做时,结果完全一样。 So, without the BodyListener the PHPUnit case gets the body though the simulated request is still empty. 因此,如果没有BodyListener ,PHPUnit案例会获取正文,尽管模拟请求仍为空。

See php:// wrappers on php.net: 请参阅php.net上的php:// wrappers:

Note: Prior to PHP 5.6, a stream opened with php://input could only be read once; 注意:在PHP 5.6之前,使用php://输入打开的流只能读取一次; the stream did not support seek operations. 流不支持搜索操作。 However, depending on the SAPI implementation, it may be possible to open another php://input stream and restart reading. 但是,根据SAPI实现,可能会打开另一个php://输入流并重新开始读取。 This is only possible if the request body data has been saved. 只有在保存了请求正文数据后才能执行此操作。 Typically, this is the case for POST requests, but not other request methods, such as PUT or PROPFIND. 通常,这是POST请求的情况,但不是其他请求方法,例如PUT或PROPFIND。

So update your PHP version or make sure you only read the input once. 因此,请更新您的PHP版本或确保您只读取一次输入。

fos_rest.decoder_provider解码后,您可以在$request->files->all() fos_rest.decoder_provider $request->files->all()找到上传的文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM