TL; DR: Не указывать данные как byte[]
, указывать их как String
.
При использовании ResponseEntity
, Spring использует зарегистрированный HttpMessageConverter
.
Если бы вы указали тип содержимого application/octet-stream
, с типом тела byte[]
, Spring использовал бы ByteArrayHttpMessageConverter
и отправил бы байты как есть.
Если вы укажете тип содержимого text/*
, например, указанный вами text/csv
, с типом тела String
, Spring будет использовать StringHttpMessageConverter
, который будет соответствующим образом кодировать текст и отправлять его. Лучше было бы явно указать charset
, например, используя тип содержимого text/csv; charset=UTF-8
, чтобы клиент знал набор символов, используемый сервером.
Поскольку вы указали тип содержимого text/csv
, нос типом кузова byte[]
Spring использует какой-то другой HttpMessageConverter
, вероятно, ObjectToStringHttpMessageConverter
, с ConversionService
, который кодирует *От 1044 * до String
как Base-64.
Примечание: для повышения производительности не очищайте автоматически каждую строку вывода. Выключите автоматическую промывку и просто сделайте окончательный flush()
, когда закончите.
Короче говоря, поскольку вам нужен текст, не конвертируйте в byte[]
. Используйте StringWriter
, чтобы сохранить все как текст:
@PostMapping(path = BASE_ROUTE + "/download", produces = "text/csv; charset=UTF-8")
public ResponseEntity<String> downloadCases(@RequestBody RequestType request) throws IOException {
try (StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter)) {
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);
writer.flush();
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, "text/csv; charset=UTF-8")
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"report.csv\"")
.body(stringWriter.toString());
}
}
Поскольку вы никогда не использовали параметр response
, он был удален.