Springdoc-openapi: Multipart Request with JSON

Created on 9 Aug 2020  路  1Comment  路  Source: springdoc/springdoc-openapi

Describe the bug

  • I try to make a simple request with multipart and JSON object but doesn't generate the right request.

An example of StackOverflow:
https://stackoverflow.com/a/25183266/4693765

To Reproduce
Steps to reproduce the behavior:

  • Spring boot 2.2.5.RELEASE
  • Spring doc 1.4.4
  • Kotlin project with:
springdoc-openapi-data-rest
springdoc-openapi-security
springdoc-openapi-kotlin

Rest controller:

 @PostMapping("test",consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
   fun saveDocu2ment(@RequestPart(value = "file",required = true) file: MultipartFile,
                     @RequestPart(required = true)  type:MailDto) {
    }

Open Api JSON

  "paths": {
    "/api/v2/mail/test": {
      "post": {
        "tags": [
          "mail-rest-controller-v-2"
        ],
        "operationId": "saveDocu2ment",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  },
                  "type": {
                    "$ref": "#/components/schemas/MailDto"
                  }
                }

Request when execute with swagger-ui:
curl -X POST "http://localhost:8080/api/v2/mail/test" -H "accept: */*" -H "Content-Type: multipart/form-data" -F "type={ "authorizationToken": "string", "to": [ "string" ], "sender": "string", "subject": "string", "bodyText": "string", "files": [ "string" ] }" -F "file=@img_payment_success.png;type=image/png"

Screenshots
Image of example request
image

Additional context
An error response of spring boot (oviusly error):
ERROR 3108 --- [nio-8080-exec-1] e.d.s.base.BaseAdviceRestController : Content type 'application/octet-stream' not supported

Most helpful comment

@jposes22,

This is not a springdoc issue: springdoc-openapi is built on top of swagger-api/swagger-ui and spring-boot.
springdoc-openapi helps generating the OpenAPI spec. And you are not reporting any inconsitency about that.

The correct code, for your sample is:

@PostMapping(value = "/test", consumes = MediaType.MULTIPART_FORM_DATA_VALUE )
@RequestBody(content = @Content(encoding = @Encoding(name = "personDTO", contentType = "application/json")))
public ResponseEntity<Void> saveDocu2ment(
        @RequestPart(value = "personDTO")  final PersonDTO personDTO,
        @RequestPart(value = "file")  final MultipartFile file) {
    return null;
}

Which produces the following OpenAPI description:

openapi: 3.0.1
info:
  title: OpenAPI definition
  version: v0
servers:
  - url: 'http://localhost:8080'
    description: Generated server url
paths:
  /test:
    post:
      tags:
        - hello-controller
      operationId: saveDocu2ment
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                personDTO:
                  $ref: '#/components/schemas/PersonDTO'
                file:
                  type: string
                  format: binary
            encoding:
              personDTO:
                contentType: application/json
      responses:
        '200':
          description: OK
components:
  schemas:
    PersonDTO:
      type: object
      properties:
        email:
          type: string
        firstName:
          type: string
        lastName:
          type: string

Unfortunately, swagger-ui doesn't handle yet the support of the encoding attribute.

As discussed here https://github.com/springdoc/springdoc-openapi/issues/396, there is a workaround is to use the type binary for the other parts: (swagger-ui scans for the file extension to add the type of the request part).

Here a working sample code: The first parameter content should be in a file (with .json extension)

@PostMapping(value = "/test", consumes = MediaType.MULTIPART_FORM_DATA_VALUE )
public ResponseEntity<Void> saveDocu2ment(
        @RequestPart(value = "personDTO") @Parameter(schema =@Schema(type = "string", format = "binary")) final PersonDTO personDTO,
        @RequestPart(value = "file")  final MultipartFile file) {
    return null;
}

>All comments

@jposes22,

This is not a springdoc issue: springdoc-openapi is built on top of swagger-api/swagger-ui and spring-boot.
springdoc-openapi helps generating the OpenAPI spec. And you are not reporting any inconsitency about that.

The correct code, for your sample is:

@PostMapping(value = "/test", consumes = MediaType.MULTIPART_FORM_DATA_VALUE )
@RequestBody(content = @Content(encoding = @Encoding(name = "personDTO", contentType = "application/json")))
public ResponseEntity<Void> saveDocu2ment(
        @RequestPart(value = "personDTO")  final PersonDTO personDTO,
        @RequestPart(value = "file")  final MultipartFile file) {
    return null;
}

Which produces the following OpenAPI description:

openapi: 3.0.1
info:
  title: OpenAPI definition
  version: v0
servers:
  - url: 'http://localhost:8080'
    description: Generated server url
paths:
  /test:
    post:
      tags:
        - hello-controller
      operationId: saveDocu2ment
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                personDTO:
                  $ref: '#/components/schemas/PersonDTO'
                file:
                  type: string
                  format: binary
            encoding:
              personDTO:
                contentType: application/json
      responses:
        '200':
          description: OK
components:
  schemas:
    PersonDTO:
      type: object
      properties:
        email:
          type: string
        firstName:
          type: string
        lastName:
          type: string

Unfortunately, swagger-ui doesn't handle yet the support of the encoding attribute.

As discussed here https://github.com/springdoc/springdoc-openapi/issues/396, there is a workaround is to use the type binary for the other parts: (swagger-ui scans for the file extension to add the type of the request part).

Here a working sample code: The first parameter content should be in a file (with .json extension)

@PostMapping(value = "/test", consumes = MediaType.MULTIPART_FORM_DATA_VALUE )
public ResponseEntity<Void> saveDocu2ment(
        @RequestPart(value = "personDTO") @Parameter(schema =@Schema(type = "string", format = "binary")) final PersonDTO personDTO,
        @RequestPart(value = "file")  final MultipartFile file) {
    return null;
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

riimeik picture riimeik  路  4Comments

urswiss picture urswiss  路  5Comments

debargharoy picture debargharoy  路  3Comments

GrmpfNarf picture GrmpfNarf  路  3Comments

kingtran2112 picture kingtran2112  路  5Comments