swagger-api / swagger-codegen

swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
http://swagger.io
Apache License 2.0
17.02k stars 6.03k forks source link

[Java][CXF] Include the file name and the proper content type in a file download #6953

Open gustavoapaz opened 6 years ago

gustavoapaz commented 6 years ago
Description

This is a feature request. I have the necessity to include the file name in the response as well as to change the content type of the response to match the one of the file. Currently, I am not able to generate a file download API that can stand on its own without the need of additional coding on the client side.

Swagger-codegen version

2.3.0

Swagger declaration file content or url

For example, to define a REST API that downloads a file you need to define something like the following in the YAML:

paths:
  /v1/files:
    get:
      summary: "get"
      produces:
      - "application/octet-stream"
      parameters:
      - name: "file"
        in: "query"
        required: true
        type: "string"
      responses:
        200:
          description: "Status 200"
          schema:
            type: "string"
            format: "binary"

This definition generates the following CXF Java server stub interface:

    @GET
    @Path("/v1/files")
    @Consumes({ "application/json" })
    @Produces({ "application/octet-stream" })
    @ApiOperation(value = "get", tags={  })
    @ApiResponses(value = { 
        @ApiResponse(code = 200, message = "Status 200", response = byte[].class) })
    public byte[] v1FilesGet(@QueryParam("file") @NotNull String file);

And the following CXF Java server stub implementation:

    public byte[] v1FilesGet(String file) {
        // TODO: Implement...

        return null;
    }

But, the return type byte[] does not allow to include the file name in the response and to change the content type of the response to match the one of the file.

Command line used for generation

..

Steps to reproduce

..

Related issues/PRs

..

Suggest a fix/enhancement

I propose that the CXF Java server stub implementation outputs a code similar to the following:

    public Response v1FilesGet(String file) {       
        byte[] fileContent = null; // TODO: Implement file content load...
        String fileName = null; // TODO: Implement file name load...

        ResponseBuilder response = Response.ok(fileContent);
        response.header("Content-Disposition", "attachment; filename=" + fileName);
        response.header("Content-length", fileContent.length);
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        String mimeType = fileNameMap.getContentTypeFor(fileName);
        response.header("content-type", mimeType + ";charset=UTF-8");
        return response.build();
    }
cbornet commented 6 years ago

Your swagger response is of type

            type: "string"
            format: "binary"

which doesn't indicate a file but a binary string response. For a file response, you must use type: "file"

gustavoapaz commented 6 years ago

@cbornet thank you very much.

I am using Restlet Studio to define my APIs.

When I use the File type in Restlet image

I get the YAML definition that I posted.

So I guess it is an issue in Restlet.

cbornet commented 6 years ago

So I guess it is an issue in Restlet.

Indeed :smile:

gustavoapaz commented 6 years ago

Issue reported to Restlet.

gustavoapaz commented 6 years ago

@cbornet when I use the swagger response of type file

type: "file"

the cxf server stub is generated like this:

public File v1FilesGet(String file) {

But, this way I can not use a file that does not exist on disk.

cbornet commented 6 years ago

I guess javax.ws.rs.core.Response return type would be more flexible here.

cbornet commented 6 years ago

I checked and all other JAX-RS generators return Response in their stub for any type of response. I think this should also be the case for CXF as it gives more control over the response (can add headers, etc...).