使用生成的客户端代码无法上传文件

问题描述 投票:1回答:1

我有一个简单的input从本地驱动器中选择文件:

<input type="file" (change)="onUpload($event)" required/>

选择文件后,我想将其上传到我的服务器。

为此,我实际上使用的是生成的客户端,它公开了该接口:

// Generated Client Code

// .. file.d.ts
export interface File {
    file?: Blob;
}

// .. rest-client.d.ts

postTrack(file, observe = 'body', reportProgress = false) {
    if (file === null || file === undefined) {
        throw new Error('Required parameter file was null or undefined when calling postTrack.');
    }
    let queryParameters = new HttpParams({ encoder: this.encoder });
    if (file !== undefined && file !== null) {
        queryParameters = queryParameters.set('file', file);
    }
    let headers = this.defaultHeaders;
    // to determine the Accept header
    const httpHeaderAccepts = [
        'multipart/form-data'
    ];
    const httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
    if (httpHeaderAcceptSelected !== undefined) {
        headers = headers.set('Accept', httpHeaderAcceptSelected);
    }
    return this.httpClient.post(`${this.configuration.basePath}/api/tracks`, null, {
        params: queryParameters,
        withCredentials: this.configuration.withCredentials,
        headers: headers,
        observe: observe,
        reportProgress: reportProgress
    });
}

上传看起来像这样:

onUpload(event) {
  this.uploadAndProgress(event.target.files);
}

uploadAndProgress(files: File[]) {

  // Method 1 - Pass file object directly
  const file = files[0];

  // Method 2 - Append file object to FormData     
  const file = new FormData();
  file.append('file', files[0]);

  this.apiGateway.postTrack(file, 'events',true)
    .subscribe((event) => {
      if (event.type === HttpEventType.UploadProgress) {
        this.percentDone = Math.round(100 * event.loaded / event.total);
      } else if (event instanceof HttpResponse) {
        this.uploadSuccess = true;
      }
    });
}

但是,它不起作用,因为POST请求URL看起来像这样:https://localhost:8443/api/tracks?file=%5Bobject%20Object%5D(用于方法1和方法2),并且我收到此响应:

{
  "timestamp": "2020-01-25T22:16:27.727+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "Current request is not a multipart request",
  "trace": "org.springframework.web.multipart.MultipartException: Current request is not a multipart request\n...",
  "path": "/api/tracks"
}

在服务器端,我有这个端点,当前负责将该文件存储在其他位置:

@RequestMapping(value = "/tracks", method = RequestMethod.POST, consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public @ResponseBody
String postTrack(
        @RequestParam("file") MultipartFile file,
        RedirectAttributes redirectAttributes
) {
    storageService.store(file);
    redirectAttributes.addFlashAttribute("message",
            "You successfully uploaded " + file.getOriginalFilename() + "!");

    return "redirect:/";
}

我不太确定要完成这项工作究竟需要做什么。

我很确定问题是我应该以Blob格式发送文件。但是,我找不到将File对象转换为Blob的方法。

angular post file-upload multipart springdoc
1个回答
0
投票

事实证明,问题出在生成的代码(see)。

总结:

@RequestParam尚不支持,但将从下一版本的]开始。

springdoc-openapi 1.2.29

还请注意,不支持consumes

@RequestMapping(value = "/tracks", method = RequestMethod.POST, consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})

相反,我必须像这样添加@ApiResponse

@RequestMapping(value = "/tracks", method = RequestMethod.POST)
@ApiResponse(description = "Successful Operation", responseCode = "200", content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE))

生成的TypeScript客户端代码现在看起来像这样:

postTrack(file, observe = 'body', reportProgress = false) {
    let headers = this.defaultHeaders;
    // to determine the Accept header
    const httpHeaderAccepts = [
        'multipart/form-data'
    ];
    const httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
    if (httpHeaderAcceptSelected !== undefined) {
        headers = headers.set('Accept', httpHeaderAcceptSelected);
    }
    // to determine the Content-Type header
    const consumes = [
        'multipart/form-data'
    ];
    const canConsumeForm = this.canConsumeForm(consumes);
    let formParams;
    let useForm = false;
    let convertFormParamsToString = false;
    // use FormData to transmit files using content-type "multipart/form-data"
    // see https://stackoverflow.com/questions/4007969/application-x-www-form-urlencoded-or-multipart-form-data
    useForm = canConsumeForm;
    if (useForm) {
        formParams = new FormData();
    }
    else {
        formParams = new HttpParams({ encoder: this.encoder });
    }
    if (file !== undefined) {
        formParams = formParams.append('file', file) || formParams;
    }
    return this.httpClient.post(`${this.configuration.basePath}/api/tracks`, convertFormParamsToString ? formParams.toString() : formParams, {
        withCredentials: this.configuration.withCredentials,
        headers: headers,
        observe: observe,
        reportProgress: reportProgress
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.