Fit*_*iti 5 php symfony api-platform.com
受影响的 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);
}
}
Run Code Online (Sandbox Code Playgroud)
相关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
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
还有我的控制器:
<?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);
}
}
Run Code Online (Sandbox Code Playgroud)
运行我的测试时,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
"""
}
Run Code Online (Sandbox Code Playgroud)
如果我替换$formData->bodyToString()by $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
Run Code Online (Sandbox Code Playgroud)
难道我做错了什么 ?还有其他方法可以在 ApiTestCase 中上传文件吗?
感谢您的帮助。