Summary: ResponseEntity<byte[]>
containing CSV is not returned as CSV
I'm writing a controller for a download button that will generate a CSV with data retrieved from another dependency.
@PostMapping(BASE_ROUTE + "/download")
public ResponseEntity<byte[]> downloadCases(@RequestBody RequestType request, final HttpServletResponse response) throws IOException {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
PrintWriter writer = new PrintWriter(outputStreamWriter, true)) {
String nextPageToken = null;
do {
ServiceResponse serviceResponse = makeServiceCall(request.getParam());
// write a String of comma separated values
writer.println(serviceResponse.getLine());
// eventually null
nextPageToken = serviceResponse.getToken();
} while (nextPageToken != null);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, "text/csv")
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"report.csv\"")
.body(outputStream.toByteArray());
}
As a test, I also tried setting the body to .body("Case ID,Assignee".getBytes(StandardCharsets.UTF_8))
. This should be equivalent to https://stackoverflow.com/a/34508533/10327093
In both cases, the response I'm getting looks like Base64. Example (shortened): Q2FzZSBJRCxBc3NpZ25lZQ==
It doesn't seem to be actually Base64. Using .body(Base64.getDecoder().decode(outputStream.toByteArray()))
gives me java.lang.IllegalArgumentException: Illegal base64 character
If I return void
and copy the outputStream to response.getOutputStream() with IOUtils.write(outputStream.toByteArray(), response.getOutputStream());
, the downloaded file is correct (CSV).
However I want to avoid calling response.getOutputStream() directly. If I get any Exception afterwards, I get the error getOutputStream() has already been called for this response
in the @ExceptionHandler
EDIT: Base64 decoding the response gives me the correct value
System.out.println(new String(Base64.getDecoder().decode("Q2FzZSBJRCxBc3NpZ25lZQ==")));
// Case ID,Assignee
It seems the byte[] is getting Base64 encoded between returning the ResponseEntity and the client (tried with Postman and browser).