Обработка ошибок для закрытых клиентов в StreamingResponseBody весной - PullRequest
0 голосов
/ 31 марта 2020

Мне было интересно, есть ли способ узнать, закрыл ли клиент соединение StreamingResponseBody, пока данные все еще записываются в выходной поток. Мой Spring Boot контроллер выглядит так:

@RestController
public class MyController {

    @PostMapping(value = "/zip")
    public ResponseEntity<StreamingResponseBody> zip(HttpServletResponse response) {
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment;filename=download.zip");

        StreamingResponseBody responseBody = outputStream -> {
            try (ZipOutputStream zipOut = new ZipOutputStream(outputStream)) {
                // loop over files
                final ZipEntry zipEntry = new ZipEntry(path);
                zipOut.putNextEntry(zipEntry);
                byte[] bytes = new byte[1024];
                int length;
                while ((length = bufferedInputStream.read(bytes)) >= 0) {
                    zipOut.write(bytes, 0, length);
                }
                zipOut.closeEntry();
            } catch (IOException e) {
                // error handling
            }
        }
        return new ResponseEntity<>(responseBody, HttpStatus.OK);
    }
}

Приложение берет некоторые файлы и помещает их в ZIP-файл в ответ. При нормальной работе это приложение работает нормально.

Если клиент прерывает загрузку ZIP-файла, приложение продолжает помещать файлы в ZIP-архив, но в конечном итоге происходит сбой с ClientAbortException (через несколько минут). Вот подробное сообщение об ошибке:

org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe
    at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:351)
    at org.apache.catalina.connector.OutputBuffer.flushByteBuffer(OutputBuffer.java:776)
    at org.apache.catalina.connector.OutputBuffer.append(OutputBuffer.java:681)
    at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:386)
    at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:364)
    at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:96)
    at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.write(OnCommittedResponseWrapper.java:645)
    at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.write(OnCommittedResponseWrapper.java:645)
    at java.util.zip.DeflaterOutputStream.deflate(DeflaterOutputStream.java:253)
    at java.util.zip.DeflaterOutputStream.write(DeflaterOutputStream.java:211)
    at java.util.zip.ZipOutputStream.write(ZipOutputStream.java:331)

Так можно ли было бы остановить обработку, связанную с этим запросом, когда клиент закрывает соединение? В противном случае полезные ресурсы будут потрачены впустую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...