首页 > 解决方案 > 确定 org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe with Spring Boot 1.5 和 Angular 5 的原因

问题描述

所以我有一个接收 GET 请求(Spring Boot)的 API,生成一个 excel 文件并将其返回给客户端(Angular)并且它可以工作但是我在下面收到以下异常,而前端收到文件的 504 响应生成的时间更大,时间更长。

Caused by: org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe
     at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:393)
     at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:426)
     at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:342)

这是获取 excel 工作簿并将其作为响应返回的 java 代码:

    public ResponseEntity<?> doReturn(ResponseDTO responseDTO, String fileName, HttpServletRequest req,
        String methodName) throws Exception {

      HttpHeaders headers = new HttpHeaders();
      headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

      Workbook workbook = responseDTO.getWorkbook();
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      try {
          workbook.write(out);
      } catch (IOException e) {
          throw e;
      } finally {
        try {
            workbook.close();
        } catch (IOException e) {
            logger.info("User: " + user + " failed to close exported file from " + methodName);
        }
      }

      ResponseEntity<?> resp = new ResponseEntity<>(out.toByteArray(), headers, HttpStatus.OK);
    }

这是发出请求的 Angular 代码:

exportwithparam(url, fileName, Params): Observable<string> {
    let Headers = new HttpHeaders().set("Authorization", "Basic " + btoa(environment.roles.basicAuth)).set("Content-Type", "application/json");
    return this.http
    .get(url, { headers: Headers, responseType: 'arraybuffer', observe: 'response', withCredentials: true, params: Params })
    .pipe(
        map(res => {
            let errmsg = "You have successfully exported " + fileName;
            if (res.ok) {
            let blob = new Blob([res.body], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
            if (window.navigator.msSaveOrOpenBlob) {
                window.navigator.msSaveBlob(blob, fileName);
            } else {
                let objectUrl = URL.createObjectURL(blob);
                let a = document.createElement('a');
                a.href = objectUrl;
                a.target = '_blank';
                a.download = fileName;
                document.body.appendChild(a);
                a.click();
            }
        }
        return errmsg;
  }),
  catchError((err: HttpErrorResponse): string => {
    if (err.status == 504) {
      throw "Gateway Time-out";
    } else {
      let errormessage = String.fromCharCode.apply(null, new Uint8Array(err.error));
      throw errormessage;
    }
  })
  )
}

我想知道我在 Java 代码中是否做错了什么会导致此异常。但是,如果是客户端断开连接,那么 Angular 有什么我可以做的吗?我曾尝试在 this.http.get 之后在 VS Code 中设置断点,似乎对于发生问题的情况,它不会流向下一行代码,而是直接进入底部的 catchError 部分。

另外我需要注意的是,当我在 localhost 中同时运行 Spring Boot 和 Angular 时,不会发生此问题。当我使用在我们的 dev/test/prod 环境中运行的 Spring Boot 进行测试时,就会发生这种情况。我知道你们中的一些人可能会说环境设置是罪魁祸首,但我只是想在我得出这个结论之前看看你们是否注意到了什么。

我还尝试将 GET 请求作为带有查询参数的 URL 发出,这些请求需要更长的时间才能返回响应,并且它还返回 504 GATEWAY TIMEOUT。

标签: javaangularspring-boot

解决方案


推荐阅读