Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Browse button for @RequestBody when mediaType is other than application/octet-stream #515

Closed
jmoraleda opened this issue Mar 28, 2020 · 5 comments

Comments

@jmoraleda
Copy link

jmoraleda commented Mar 28, 2020

I have not figured out how to get the swagger-ui to display a Browse button when my @PostMapping annotation has a consumes attribute with a value other than application/octet-stream.

From the documentation at https://swagger.io/docs/specification/describing-request-body/file-upload/ I have tried to set:

 @RequestBody(content = @Content(schema  = @Schema(format = "binary", type="string"))

but this makes no difference. The moment I set consumes to a value other than application/octet-stream I swagger displays a box to input text instead of a browse button. Am I doing something wrong, or is this a bug?

@bnasslahsen
Copy link
Contributor

@jmoraleda,

Please have a look at this page:

If you are reporting a bug, please help to speed up problem diagnosis by providing as much information as possible:

  • You need to describe your context (the title of an issue is not enough)
  • What version of spring-boot you are using?
  • What modules and versions of springdoc-openapi are you using?
  • What are the actual and the expected result using OpenAPI Description (yml or json)?
  • Provide with a sample code (HelloController) or Test that reproduces the problem

@jmoraleda
Copy link
Author

jmoraleda commented Mar 28, 2020

Thank you @bnasslahsen . These are more details that hopefully help clarify the issue:

I am using springdoc-openapi-ui version 1.3.0 from maven central.
I am using spring-boot-starter-parent version 2.2.5.RELEASE from maven central.

consumes=application/octet-stream Correct behavior (What I expect)

When specifying that a controller method consumes media type application/octet-stream, the swagger ui display a browse button to upload a file when testing the method. This is the correct behavior as far as I understand.

In particular, when trying out the following code in swagger-ui:

  @PostMapping(path="/server/uploadpdf",
               consumes=MediaType.APPLICATION_OCTET_STREAM_VALUE)
  public void uploadpdf(
              @RequestBody 
              byte[] pdf ) {}

it correctly displays:
image

consumes=application/pdf WITHOUT attributes in @RequestBody Correct behavior (What I expect)

Let's say I specify that the client must upload a PDF document and not an arbitrary octet stream by specifying that the method consumes media type application/pdf. In this case the swagger ui displays a text entry box when testing the method. This is also the correct behavior as far as I understand.

In particular, when trying out the following code in swagger-ui:

  @PostMapping(path="/server/uploadpdf",
              consumes=MediaType.APPLICATION_PDF_VALUE)
  public void uploadpdf(
              @RequestBody
              byte[] pdf) {}

it correctly displays:
image

consumes=application/pdf WITH attributes in @RequestBody Incorrect behavior (Not what I expect)

I want to tell swagger to show me an upload button and not a text box while keeping the restriction that the client must send a pdf. According to my understanding of https://swagger.io/docs/specification/describing-request-body/file-upload/ this is achieved by adding attributes content = @Content(schema = @Schema(format = "binary", type="string")) to the @RequestBody

In particular, when trying out the following code in swagger-ui:

  @PostMapping(path="/server/uploadpdf",
              consumes=MediaType.APPLICATION_PDF_VALUE)
  public void uploadpdf(
              @RequestBody(content = @Content(schema  = @Schema(format = "binary", type="string")))
              byte[] pdf) {}

it displays:
image

This is not what I expect. The swagger ui still displays a text box and not an upload button. Is this a bug? If it is not a bug, then how do you interpret the documentation I point to above, and what is the correct way to tell swagger to display an upload button and not an edit box?

By the way, in case it is relevant, I have noticed that adding attributes to the @RequestBody annotation has had an effect :The sample code shown in the text box does is now not a json object but a raw string.

Thank you.

@bnasslahsen
Copy link
Contributor

bnasslahsen commented Mar 29, 2020

Hi @jmoraleda,

As you can see, if you just change the MediaType (image/png), the browse button will be displayed correctly in the swagger-ui.
This behaviour is not related to springdoc-openapi, and you can submit any enhancement to swagger-ui project.

Also, you can have a look at the specification:

@jmoraleda
Copy link
Author

jmoraleda commented Mar 29, 2020

Hi @bnasslahsen,

Thank you for your quick response! I just tried image/png and you are indeed correct: It displays a button.

I feel a mechanism for overriding the auto-detected default of whether to use an upload button or an input text box would be very useful because there is a large and growing number of media types and use cases; and in addition, any application can define its own custom media type application/x-foobar. I will close this issue and bring it up as a feature request in the swagger-ui project. Thank you again.

@falk-stefan
Copy link

Sorry to hijack this issue but I am trying something similar. My goal is to create an endpoint for uploading larger files. These files should be accepted as a byte-stream s.t. they can be written on-the-fly without consuming too much memory.

What I go so far is something like this:

@RequestMapping(
        value = "/tracks/{trackId}/file", 
        method = RequestMethod.POST, 
        consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE
)
@ApiResponse(
        description = "Successful Operation", 
        responseCode = "200", 
        content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)
)
public @ResponseBody
Track uploadTrackFile(@PathVariable(name = "trackId") Long trackId, HttpServletRequest request) {
    return null;
}

which produces the following output in the swagger.yaml:

/user/tracks/{trackId}/file:
  post:
    tags:
    - track-controller
    operationId: uploadTrackFile
    parameters:
    - name: trackId
      in: path
      required: true
      schema:
        type: integer
        format: int64
    responses:
      "200":
        description: Successful Operation
        content:
          application/json: {}

This doesn't look right - I'm kind of missing the APPLICATION_OCTET_STREAM_VALUE input definition as well as the correct response-content definition which should be:

content:
  '*/*':
    schema:
      $ref: '#/components/schemas/Track'

Any idea how I can do this right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants