微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

控制器端请求中未设置 ApiTestCase 中上传的文件

如何解决控制器端请求中未设置 ApiTestCase 中上传的文件

受影响的 API 平台版本:2.5.7

在带有 FormDataPart 的 ApiTestCase 中发出请求时,控制器端的 $request->files 为空。

这是我的测试:

<?PHP

namespace App\Tests\Controller;

use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\Multipart\FormDataPart;

class ImportRequestTest extends ApiTestCase
{
    public function testPostOk(): void
    {
        $client = static::createClient();

        $data = ['file' => DataPart::fromPath(__DIR__.'/../path/to/file.csv')];
        $formData = new FormDataPart($data);
        $headers = $formData->getPreparedHeaders();

        $client->request(
            'POST','/import_requests/{my-request-id}/upload',[
                'headers' => $headers->toArray(),'body' => $formData->bodyToString(),]
        );

        $this->assertResponseIsSuccessful();
        $this->assertResponseStatusCodeSame(204);
    }
}

相关的 ApiResource :

<?PHP

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use App\Controller\ImportRequestUpload;

/**
 * @ApiResource(
 *    itemOperations={
 *        "get",*        "delete",*        "put",*        "upload"={
 *            "method"="POST",*            "path"="/import_requests/{id}/upload",*            "controller"=ImportRequestUpload::class,*            "deserialize"=false,*            "openapi_context"={
 *                "requestBody"={
 *                    "content"={
 *                        "multipart/form-data"={
 *                            "schema"={
 *                                "type"="object",*                                "properties"={
 *                                    "file"={
 *                                        "type"="string",*                                        "format"="binary"
 *                                    }
 *                                }
 *                            }
 *                        }
 *                    }
 *                }
 *            }
 *        }
 *    },*    collectionoperations={
 *        "get",*        "post"
 *    }
 * )
*/
final class ImportRequest
{
    // ...
}

还有我的控制器:

<?PHP

namespace App\Controller;

use App\Entity\ImportRequest;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

final class ImportRequestUpload
{
    public function __invoke(ImportRequest $data,Request $request)
    {
        /** @var null|UploadedFile $uploadedFile */
        $uploadedFile = $request->files->get('file');

        if (null === $uploadedFile) {
            throw new BadRequestHttpException('"file" is required.');
        }

        // ...
        
        return new JsonResponse(null,Response::HTTP_NO_CONTENT);
    }
}

运行我的测试时,ImportRequestUpload 控制器抛出 BadRequestHttpException('"file" is required.')。 奇怪的是,当我将它们转储到控制器中时,我的请求的内容标题似乎没问题:

Symfony\Component\HttpFoundation\Request {
  ...
  +server: Symfony\Component\HttpFoundation\ServerBag {#4930
    #parameters: array:25 [
      ...
      "CONTENT_TYPE" => "multipart/form-data; boundary=hqdh0ikk"
      "REQUEST_METHOD" => "POST"
      ...
    ]
  }
  +files: Symfony\Component\HttpFoundation\FileBag {#4931
    #parameters: []
  }
  ...
  +headers: Symfony\Component\HttpFoundation\HeaderBag {#4941
    #headers: array:15 [
      ...
      "content-type" => array:1 [
        0 => "multipart/form-data; boundary=hqdh0ikk"
      ]
      ...
    ]
  }
  #content: """
    --hqdh0ikk\r\n
    Content-Type: text/csv\r\n
    Content-transfer-encoding: 8bit\r\n
    Content-disposition: form-data; name="file"; filename="import_ok_1.csv"\r\n
    \r\n
    header1,header2\n
    value1,value2\n
    \r\n
    --hqdh0ikk--\r\n
    """
}

如果我将 $formData->bodyToString() 替换为 $formData->bodyToIterable()(最初在 HttpClient 文档 https://symfony.com/doc/current/http_client.html#uploading-data 中建议),我会收到以下错误

TypeError : Argument 6 passed to Symfony\Component\browserKit\Abstractbrowser::request() must be of the type string or null,object given,called in /srv/api/vendor/api-platform/core/src/Bridge/Symfony/Bundle/Test/Client.PHP on line 126
 /srv/api/vendor/symfony/browser-kit/Abstractbrowser.PHP:341
 /srv/api/vendor/api-platform/core/src/Bridge/Symfony/Bundle/Test/Client.PHP:126

我做错了什么吗?有没有其他方法可以在 ApiTestCase 中上传文件

感谢您的帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。