SwaggerCodegen + Springでバイナリファイルを返すAPI


バージョン

  • OpenAPI Specification 2.0

  • io.springfox:spring-swagger2: 2.8.0

  • io.swagger:swagger-core: 1.5.18

やりたいこと

Jxlsを使用してサーバからExcelファイルをダウンロードするAPIがあるのですが、Jxls出力に必要なデータをMVCのModelクラスにつっこんで、Jxls出力を行うViewを作成して、そこに任せています。(PDFファイルも同じようにViewでやっています)

そのため、Controllerの戻り値としては次のようにStringになるわけです。

@GetMapping("/download")
public String downloadExcel() {
    ...
    return "jxlsView"
}

これをそのままSwaggerでAPI生成すると、/v2/api-docsは次のような定義になります。

"path": {
    "/download": {
        "get": {
            "response": {
                 200: {
                     ...
                     "schema": {
                         "type": "string"
                     }
                 }
                 ...

これだと、Swagger-Codegenで生成されるクライアント用コードもStringのままになってしまいます。
これをバイナリ用の型(JSの場合はBlob)にするには、OpenAPIの仕様にあわせて、つぎのようにする必要があります。

"path": {
    "/download": {
        "get": {
            "response": {
                 200: {
                     ...
                     "schema": {
                         "type": "file"
                     }
                 }
                 ...

どうするか

@ApiOperationアノテーションを使用します。
responseにクラスを指定することで、DTOクラスをスキーマに指定することができますが、ここにMultipartFile.classを指定することでバイナリファイルのための定義を得ることができます。

import org.springframework.web.multipart.MultipartFile;

@GetMapping("/download")
@ApiOperation(name = "API名", nickname = "ユニークなAPI名", response = MultipartFile.class)
public String downloadExcel() {
    ...
    return "jxlsView"
}

補足

OpenAPI Specification 3 だと、バイナリファイルの定義は次のようになります。

"path": {
    "/download": {
        "get": {
            "response": {
                 200: {
                     ...
                     "schema": {
                         "type": "string",
                         "format": "binary"
                     }
                 }
                 ...

上記のバージョンでは、SpringfoxのほうがまだOpenAPI3に対応していないようです。

今後、SwaggerCore側とSpringfox側でどのタイミングでOpenAPI3に変化していくのかは、注意が必要そうです。

参考

どこにもドキュメント書いてなくて、見つけるのに2日かかりました・・・