使用OpenAPI Generator-Plugin进行客户端文件下载

huangapple go评论99阅读模式
英文:

Client-side file download with OpenAPI Generator-Plugin

问题

I'm trying to implement a REST API using OpenAPI (v3.0.3) and the openapi-generator-maven-plugin (v6.6.0). I want the plugin to generate both server and client from the specification.

I'm trying to implement a method to download a (ZIP) file, which I imagine would be a rather common operation, but I cannot get it to work on the client side. And unfortunately, my search didn't turn up any useful hints, so I'm asking a new question. In the spec, I have written:

  /download:
    get:
      operationId: download
      responses:
        "200":
          description: Success
          content:
            application/zip:
              schema:
                type: string
                format: binary

The server side (generator spring) is generated as expected and returns a ResponseEntity of type "Resource" (I have implemented the method to return a Spring InputStreamResource). When calling the server endpoint with a hand made client, it works as expected and I can read the InputStream without problem.

The generated client however (generator java, with library native) is not really doing what I think it should. Here is a part of the generated download method:

  public ApiResponse<File> downloadWithHttpInfo() throws ApiException {
    HttpRequest.Builder localVarRequestBuilder = downloadRequestBuilder();
    try {
      HttpResponse<InputStream> localVarResponse = memberVarHttpClient.send(
          localVarRequestBuilder.build(),
          HttpResponse.BodyHandlers.ofInputStream());
      if (memberVarResponseInterceptor != null) {
        memberVarResponseInterceptor.accept(localVarResponse);
      }
      try {
        if (localVarResponse.statusCode()/ 100 != 2) {
          throw getApiException("download", localVarResponse);
        }
        return new ApiResponse<File>(
          localVarResponse.statusCode(),
          localVarResponse.headers().map(),
          localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<File>() {}) // closes the InputStream
        );
      } finally {
      }

First, it returns a response of type file...Ok, I could live with that. But it just handles the response wrong: First, it retrieves a HttpResponse. That is correct and gets the input stream, but then it tries to map the response body through a JSON mapper (memberVarObjectMapper). Which is obviously wrong since the return type in the spec is "application/zip", so the method breaks here with a JSON parse error.

So, my questions:

  1. Should I change my spec in some way to make it clear(er) to the generator what I want?
  2. Can I get the client to not use the JSON mapper and instead directly return the InputStream from the response?
  3. If there is no workaround, is there another generator library which works better? I wanted to use native since we're using Java 17, but if there's other generators which work and rely on external libraries I guess I have use one of those.
英文:

I'm trying to implement a REST API using OpenAPI (v3.0.3) and the openapi-generator-maven-plugin (v6.6.0). I want the plugin to generate both server and client from the specification.

I'm trying to implement a method to download a (ZIP) file, which I imagine would be a rather common operation, but I cannot get it to work on the client side. And unfortunately, my search didn't turn up any useful hints, so I'm asking a new question. In the spec, I have written:

  /download:
    get:
      operationId: download
      responses:
        &quot;200&quot;:
          description: Success
          content:
            application/zip:
              schema:
                type: string
                format: binary

The server side (generator spring) is generated as expected and returns a ResponseEntity of type "Resource" (I have implemented the method to return a Spring InputStreamResource). When calling the server endpoint with a hand made client, it works as expected and I can read the InputStream without problem.

The generated client however (generator java, with library native) is not really doing what I think it should. Here is a part of the generated download method:

  public ApiResponse&lt;File&gt; downloadWithHttpInfo() throws ApiException {
    HttpRequest.Builder localVarRequestBuilder = downloadRequestBuilder();
    try {
      HttpResponse&lt;InputStream&gt; localVarResponse = memberVarHttpClient.send(
          localVarRequestBuilder.build(),
          HttpResponse.BodyHandlers.ofInputStream());
      if (memberVarResponseInterceptor != null) {
        memberVarResponseInterceptor.accept(localVarResponse);
      }
      try {
        if (localVarResponse.statusCode()/ 100 != 2) {
          throw getApiException(&quot;download&quot;, localVarResponse);
        }
        return new ApiResponse&lt;File&gt;(
          localVarResponse.statusCode(),
          localVarResponse.headers().map(),
          localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference&lt;File&gt;() {}) // closes the InputStream
        );
      } finally {
      }

First, it returns a response of type file...Ok, I could live with that. But it just handles the response wrong: First, it retrieves a HttpResponse<InputStream>. That is correct and gets the input stream, but then it tries to map the response body through a JSON mapper (memberVarObjectMapper). Which is obviously wrong since the return type in the spec is "application/zip", so the method breaks here with a JSON parse error.

So, my questions:

  1. Should I change my spec in some way to make it clear(er) to the generator what I want?
  2. Can I get the client to not use the JSON mapper and instead directly return the InputStream from the response?
  3. If there is no workaround, is there another generator library which works better? I wanted to use native since we're using Java 17, but if there's other generators which work and rely on external libraries I guess I have use one of those.

答案1

得分: 0

我昨天遇到了同样的问题。我切换到使用 resttemplate 库,并将 useAbstractionForFiles 设置为 true,那就可以了。我本来更喜欢使用原生库,但似乎这可能是一个没有得到很多关注的 bug:https://github.com/OpenAPITools/openapi-generator/issues/3672

英文:

I just ran into the same thing yesterday. I switched to using resttemplate library with useAbstractionForFiles set to true, and that worked. I would prefer to have used the native library, but it seems it may be a bug without much traction: https://github.com/OpenAPITools/openapi-generator/issues/3672

huangapple
  • 本文由 发表于 2023年7月13日 14:57:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76676681.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定