I was wondering if there is a way to find out if a client has closed the connection of a StreamingResponseBody while data is still being written to the outputstream. My Spring Boot controller looks like this:
@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);
}
}
The application takes some files and puts them in a ZIP file as response. Under normal operation, this application works fine.
If the client aborts the download of the ZIP file, the application continues to put files in the ZIP, but fails eventually with a ClientAbortException (after several minutes). Here is a detailed error message:
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)
So would it be possible to stop the processing related to this request when the client closes the connection? Otherwise useful resources would be wasted.