api-platform / api-platform

🕸️ Create REST and GraphQL APIs, scaffold Jamstack webapps, stream changes in real-time.
https://api-platform.com
MIT License
8.69k stars 962 forks source link

Handling File Upload Error #2713

Closed sta2m closed 2 months ago

sta2m commented 5 months ago

API Platform version(s) affected: 3.3.3

Description

I have an issue when doing a POST request to upload a file, using the example from the docs

Error : Could not resolve argument $data of \"api_platform.action.placeholder::__invoke()\", maybe you forgot to register the controller as a service or missed tagging it with the \"controller.service_arguments\"?"

Same as : https://github.com/api-platform/api-platform/issues/2539#issuecomment-2098595585

How to reproduce

See docs

Possible Solution

This workaround work for me : https://github.com/api-platform/api-platform/issues/2539#issuecomment-1790341634

Additional Context

My conf :

    title: Hello API Platform
    version: 1.0.0
    # Mercure integration, remove if unwanted
    mercure:
        enabled: false
        include_type: true
    formats:
        jsonld: ['application/ld+json']
        multipart: [ 'multipart/form-data' ]
    docs_formats:
        jsonld: ['application/ld+json']
        jsonopenapi: ['application/vnd.openapi+json']
        html: ['text/html']
    # Good defaults for REST APIs
    defaults:
        stateless: true
        cache_headers:
            vary: ['Content-Type', 'Authorization', 'Origin']
        extra_properties:
            standard_put: true
            rfc_7807_compliant_errors: true
    # change this to true if you use controllers
    use_symfony_listeners: true
    keep_legacy_inflector: false
    swagger:
        api_keys:
            JWT:
                name: Authorization
                type: header
dynalouis commented 4 months ago

Same issue here !

asalisaf commented 4 months ago

Try to specify input format in operation level instead of specifying in global config.


           new Post(
                ...
                controller: FileController::class,
                deserialize: false,
                inputFormats: ['multipart' => ['multipart/form-data']],
                openapi: new Operation(
                    requestBody: new RequestBody(
                        content: new ArrayObject([
                            'multipart/form-data' => [
                                'schema' => [
                                    'type' => 'object',
                                    'properties' => ['file' => ['type' => 'string', 'format' => 'binary']],
                                ],
                            ],
                        ])
                    )
                )
            ),
sta2m commented 4 months ago

My POST config :


new Post(
            inputFormats: ['multipart' => ['multipart/form-data']],
            processor: UploadOnFile::class,
            deserialize: false,
            openapi: new Model\Operation(
                requestBody: new Model\RequestBody(
                    content: new \ArrayObject([
                        'multipart/form-data' => [
                            'schema' => [
                                'type' => 'object',
                                'properties' => [
                                    'file' => [
                                        'type' => 'string',
                                        'format' => 'binary'
                                    ]
                                ]
                            ]
                        ]
                    ])
                )
            )
        ),```
asalisaf commented 4 months ago

try removing multipart in format section in global config(api_platform.yml)

d0niek commented 4 months ago

My error is:

Deserialization for the format \"multipart\" is not supported.

I've follow the docs from up to this point and after POST /media_objects I got an error.

Here I see "new" change which doesn't work.

| Vich doesn't manage the file creation and set the filePath.

It looks like custom processor is needed. Is it true?

d0niek commented 4 months ago

@sta2m do you have any progress in this issue?

fvozar commented 2 months ago

I had the same issue and I had to solve it with custom provider. Here is my implementation

public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
    {
        $uploadedFile = $context['request']->files->get('file');
        if (!$uploadedFile) {
            throw new BadRequestHttpException('"file" is required');
        }
        $mediaObject = new MediaObject();
        $mediaObject->file = $uploadedFile;

        return $mediaObject;
    }

MediaObject is my entity with Vich Uploadable attribute.

The Post operation mapping is the same, but I have read: false there as well

soyuka commented 2 months ago

We successfully handle file upload in many of our projects, closing as non-issue

d0niek commented 2 months ago

In my case the problem was that docs aren't in good order.

After section Resolving the File URL should be a Handling the Multipart Deserialization (!)