Skip to content

Allow file upload support using other mime types #326

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

Closed
guw opened this issue Apr 12, 2015 · 10 comments
Closed

Allow file upload support using other mime types #326

guw opened this issue Apr 12, 2015 · 10 comments

Comments

@guw
Copy link

guw commented Apr 12, 2015

APIs allow for many different ways of uploading files. I'd like to be able to document the following in Swagger.

swagger: '2.0'

info:
  title: File Put Sample
  version: "1.0.0"
paths:
  /attachments/{name}:
    put:
      summary: Upload
      parameters:
        - name: name
          in: path
          description: the name of an attachment
          required: true
          type: string
        - name: content
          in: body
          description: the attachment content
          required: true
          schema:
            type: file
      consumes:
        - application/octet-stream
      responses:
        200:
          description: the upload was successful

This basically describes an API that can PUT file content onto a specific url. By setting consumes to other mime-typed then application/octet-stream (eg., image/png) it's also possible to express what content must be uploaded.

@BigSocial
Copy link

👍 for both PUT and POST

Java/Jersey code like this...

@POST
@Path("/{transformId}.bin")
@Consumes({MediaType.APPLICATION_OCTET_STREAM})
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(
        value = "Starts a Job on the uploaded file",
        response = Job.class)
public Response runTransformRaw(
   @ApiParam(value = "Id of the transform", required = true)
   @PathParam("transformId") final String id,
   @ApiParam(value = "File to upload", required=true) InputStream inputStream) {
    return runTransformFromInputStream(id, inputStream);
}

...should generate a Parameter Object something like this...

{
name: "file",
in: "body",
description: "File to upload",
required: true,
type: "file"
}

...which Swagger UI and Sawgger Codegen should understand as the file being the entire binary body per RFC 2046 section 4.5.1. The justification for this is that it's likely to perform better than using multipart/form-data for high volume file transfer to a REST API.

@mohsen1
Copy link
Contributor

mohsen1 commented Jun 8, 2015

also PATCH

@webron
Copy link
Member

webron commented Jun 8, 2015

Umm, the issue isn't with the method, is with the mime type. There's no problem with put/post/patch/get/options/whatever for file uploads. Swagger doesn't care about that.

@BigSocial
Copy link

@webron yeah, the focus should have been in an Operation Object where consumes is application/octet-stream.

@webron
Copy link
Member

webron commented Jun 8, 2015

It's time to change the title.

@webron webron changed the title Allow to PUT files in body Allow file upload support using other mime types Jun 8, 2015
@webron
Copy link
Member

webron commented Jul 31, 2015

We just finalized some discussion over in #50, so I'd like to propose a workaround for this issue.

In general, perhaps we shouldn't have gone with the file type anyways and need to provide better support for binary data transfer in general.

Based on #50, you should be able to use "type": "string", "format": "binary" instead of file type to overcome it.

@BigSocial
Copy link

So I'm a little confused about the implications of all this. If I may be concrete for a minute.

This code...

@POST
@Path("/bin")
@Consumes({MediaType.APPLICATION_OCTET_STREAM})
@Produces({MediaType.APPLICATION_JSON})
@ApiOperation(
        value = "Create a new Source from an uploaded file. This version expects the file as the raw contents of the request.",
        response = Source.class
        )
public Response makeSourceRaw(
        @ApiParam(value = "A file", required = true) InputStream inputStream
        )

...works perfectly (i.e. it allows access to the unencoded body) but currently generates this Swagger 2.0...

parameters: [
    {
        in: "body",
        name: "body",
        description: "A file",
        required: true,
        schema: {
             $ref: "#/definitions/InputStream"
        }
    }
]

...this, reasonably useless, Swagger UI...

image

...and generates a Java client that treats InputStream as if it were part of my model (i.e. creates a io.swagger.client.model.InputStream class), not an important concept in Java/Jersey, forcing me to hack the generated output to make it work.

Does "type": "string", "format": "binary" somehow magically fix this?

Is there any way right now to make Swagger (core, UI, codegen, etc.) understand that an InputStream param should be treated as a "raw" file upload?

@webron
Copy link
Member

webron commented Oct 9, 2015

@BigSocial - I believe there isn't a solution for it yet in swagger-core, and it would be great if you could open an issue there so we'd handle it.

@BigSocial
Copy link

@webron Sorry, missed your initial response. Issue added to swagger-core.

@fehguy
Copy link
Contributor

fehguy commented Feb 1, 2017

See #878

@fehguy fehguy closed this as completed Feb 1, 2017
kevinoid added a commit to kevinoid/api-spec-converter that referenced this issue Mar 25, 2019
An OAS v3 spec with an operation to send a file in a request body, as
described in [Considerations for File Uploads][1]:

    requestBody:
      content:
        application/octet-stream:
          schema:
            type: string
            format: binary

api-spec-converter converts this to:

    consumes:
      - application/octet-stream
    parameters:
      - in: formData
        name: body
        type: file
    responses:
      '204':
        description: Success
    operationId: uploadFile

Which is invalid both because `type` is only allowed "if `in` is any
value other than `body`" and because "if type is `file`, the consumes
MUST be either `multipart/form-data`,
`application/x-www-form-urlencoded` or both".[2]

Instead, preserve the schema from the OAS3 spec, if present, or use
`type: "string"` with `format: "binary"` as recommended in
OAI/OpenAPI-Specification#326.  Also, don't copy the non-schema
properties, which are invalid for `in: "body"`.

[1]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#considerations-for-file-uploads
[2]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#fixed-fields-7

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
kevinoid added a commit to kevinoid/api-spec-converter that referenced this issue Mar 25, 2019
An OAS v3 spec with an operation to send a file in a request body, as
described in [Considerations for File Uploads][1]:

    requestBody:
      content:
        application/octet-stream:
          schema:
            type: string
            format: binary

api-spec-converter converts this to:

    consumes:
      - application/octet-stream
    parameters:
      - in: formData
        name: body
        type: file
    responses:
      '204':
        description: Success
    operationId: uploadFile

Which is invalid because ["if type is `file`, the consumes MUST be either
`multipart/form-data`, `application/x-www-form-urlencoded` or both"][2].

Instead, preserve the schema from the OAS3 spec, if present, or use
`type: "string"` with `format: "binary"` as recommended in
OAI/OpenAPI-Specification#326.  Also, don't copy the non-schema
properties, which are invalid for `in: "body"`.

[1]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#considerations-for-file-uploads
[2]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#fixed-fields-7

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
rbren pushed a commit to LucyBot-Inc/api-spec-converter that referenced this issue Mar 25, 2019
* openapi_3 to swagger_2: Fix invalid body parameter

An OAS v3 spec with an operation to send a file in a request body, as
described in [Considerations for File Uploads][1]:

    requestBody:
      content:
        application/octet-stream:
          schema:
            type: string
            format: binary

api-spec-converter converts this to:

    consumes:
      - application/octet-stream
    parameters:
      - in: formData
        name: body
        type: file
    responses:
      '204':
        description: Success
    operationId: uploadFile

Which is invalid because ["if type is `file`, the consumes MUST be either
`multipart/form-data`, `application/x-www-form-urlencoded` or both"][2].

Instead, preserve the schema from the OAS3 spec, if present, or use
`type: "string"` with `format: "binary"` as recommended in
OAI/OpenAPI-Specification#326.  Also, don't copy the non-schema
properties, which are invalid for `in: "body"`.

[1]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#considerations-for-file-uploads
[2]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#fixed-fields-7

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>

* openapi_3 to swagger_2: Support more+multiple types

The transformation for application/octet-stream should work for any
media type.  Instead of failing with 'unsupported request body media
type', apply the transformation.

Additionally, include all media types (but not media ranges, which are
not allowed in Swagger 2) from `content` in `consumes`.  This avoids
losing information for operations which consume multiple types (e.g.
`image/gif` and `image/png`).

If `consumes` would be empty because the OAS3 content object only
contained media ranges, use `application/octet-stream` as a generic
catch-all type.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>

* openapi_3 to swagger_2: Preserve all request body types

As with upload types, operations may consume both formData types or
multiple JSON types.  Preserve these as well.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
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

5 participants