Skip to content

[HttpKernel] RFC: Support UploadedFile when deserialize requests with #[MapRequestPayload] attribute #60440

Open
@tsantos84

Description

@tsantos84

Description

Currently, RequestPayloadValueResolver only deserializes $request->request->all() into the target class. This behavior requires uploaded files to be mapped separately using another argument with the #[MapUploadedFile] attribute:

public function __invoke(
    #[MapRequestPayload] MyRequest $myRequest,
    #[MapUploadedFile] UploadedFile $myFile
) {
}

This separation forces developers to manually split file handling from the main request payload, even when the uploaded files conceptually belong to the same data structure.

It would be much more ergonomic and intuitive if the uploaded file could be included directly within the request DTO. For example:

class MyRequest {
    public ?string $foo = null;
    public ?UploadedFile $file = null;
}

This would allow the controller signature to be simplified to:

public function __invoke(#[MapRequestPayload] MyRequest $myRequest) {
}

While it might be possible to work around this with custom denormalizers (not yet tested), I believe this use case is common enough to warrant native support in Symfony core.

Proposal

Extend RequestPayloadValueResolver (and possibly the serializer) to support injecting UploadedFile instances into DTOs during deserialization, allowing them to be mapped directly as properties.

Proposal requirements

  • It should allow to add validation constraints to files as well.
  • It should handle multi-level data like Symfony Form does.

Benefits

  • Cleaner controller method signatures
  • Better encapsulation of request data
  • Less boilerplate and manual mapping
  • More aligned with how form handling works

Looking forward to hearing your thoughts and if this could be a candidate for inclusion in a future Symfony release.

Something to consider

Allowing UploadedFile to be included in MapRequestPayload could set a precedent for supporting other request sources, such as query strings and headers. If that happens, we might need to define a clear priority order for how data from different parts of the request (body, query, headers, files) should be merged.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions