8

I want to download a file from the server, and I define the swagger file as follows:

swagger: '2.0'

################################################################################
# API Information
################################################################################
info:
  version: v0
  title: XXX REST API

host: api.xxx.io
basePath: /v0

schemes:
  - http
  - https
produces:
  - application/json

################################################################################
# Security
################################################################################


################################################################################
# Parameters
################################################################################
parameters:
  productId:
    name: productId
    in: path
    description: The product identifier
    type: string
    required: true

################################################################################
# Paths
################################################################################
paths:
  /products:
    get:
      description: Get the list of products
      operationId: getProducts
      responses:
        200:
          description: OK
          schema:
            type: array
            items:
              $ref: '#/definitions/Product'

  /resources/{productId}:
    parameters:
      - $ref: '#/parameters/productId'
    get:
      description: Get resources of a product
      operationId: getResourcesByProductId
      produces:
        - application/octet-stream
      responses:
        200:
          description: OK
          schema:
            type: file

################################################################################
# Definitions
################################################################################
definitions:
  Product:
    type: object
    required:
      - id
    properties:
      id:
        type: string
      name:
        type: string
      category:
        type: array
        items:
          type: string
      description:
        type: string
      price:
        type: number
      thumbnailUri:
        type: string
      previewUris:
        type: array
        items:
          type: string
      resources:
        type: array
        items:
          $ref: '#ResourceMeta'

And the api is as follows:

@javax.annotation.Generated(value = "class io.swagger.codegen.languages.SpringCodegen", date = "2016-10-24T17:56:03.446+08:00")

@Controller
public class ResourcesApiController implements ResourcesApi {

    public ResponseEntity<File> getResourcesByProductId(
@ApiParam(value = "The product identifier",required=true ) @PathVariable("productId") String productId


) {
        // do some magic!
        return new ResponseEntity<File>(HttpStatus.OK);
    }

}

My controller is as follows:

@Controller
public class ResourceController implements ResourcesApi {

    private final Logger logger = Logger.getLogger(ResourceController.class);

//    @RequestMapping(value="/resources/{productId}", method= RequestMethod.GET)
    public ResponseEntity<File> getResourcesByProductId(@ApiParam(value = "The product identifier", required = true) @PathVariable("productId") String productId) {
        String path = "resources" + File.separator + productId;
        File file = new File(path);
        FileSystemResource fileSystemResource = new FileSystemResource(file);
        InputStreamResource inputStreamResource = null;
        try {
            inputStreamResource = new InputStreamResource(fileSystemResource.getInputStream());
        } catch (IOException e) {
            logger.error(e.toString());
        }

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName()));

        return ResponseEntity
                .ok()
                .headers(headers)
                .contentLength(file.length())
                .body(file);
    }

}

However, when I run the application, it return a file but only contains the metadata of the file instead of its content. How can I make it return the file content? Thanks!

Niubility
  • 577
  • 5
  • 19

1 Answers1

-2

Use the InputStreamResource to return the file contents:

return new ResponseEntity(inputStreamResource, headers, HttpStatus.OK);
Joseph Earl
  • 23,351
  • 11
  • 76
  • 89
  • Yes, I know that using inputstreamresource will return the file content. But how should I define the restful api in the first file? Now according to my definition in the first file, it generates a function that returns ResponseEntity not ResponseEntity as in the second file... – Niubility Oct 26 '16 at 02:29
  • It doesn't make a lot of sense to return a file directly as response. As you've discovered, a File object is really just a container for the path and metadata for an actual file on a file system, it doesn't contain the file contents. So if you send the user a `File("/root/dev/file.txt")` object, they will get a `File` object but it will be pointing to the path `/root/dev/file.txt` on *their* filesystem. File objects are not useful for transferring files, only information about files (like where they are). – Joseph Earl Oct 26 '16 at 08:02
  • Eh, maybe you haven't understood what I mean:) I've exactly learnt that ResponseEntity doesnot meets our intention. However, according to the Swagger api definition, it generates api code that just returns ResponseEntity not ResponseEntity. In fact, the second code file is not written by me. It's generated by Swagger code generator.:D So do you know how to write the right api definition in the first file? – Niubility Oct 27 '16 at 02:51
  • 2
    Have you managed to find solution? I'm having similar problem right now. – Dcortez Mar 21 '17 at 14:51
  • Sorry, I haven't found a solution. And I choose another way instead. – Niubility Apr 11 '17 at 06:46
  • 1
    What is the alternate solutions for this ? – abhishekhp Nov 14 '18 at 02:17