I'm writing a CSV file with some accents, encoded in UTF-8. The problem is that when I try to open the file with Excel, the content is still messed up. I have to open my file with Sublime Text and save it in "UTF-8 with BOM" in order to have a correct file (saving the file as simple UTF-8 does not work). I read many SO questions and tried to apply the solutions, but none of them worked. I can't figure out if this is a backend issue when I write my file, or a frontend issue when I download it.
@Transactional
@RequestMapping(method = RequestMethod.GET, path = "/exportStreets")
public void exportStreets(@RequestParam(value = "city", required = false) Long cityId, HttpServletResponse response) throws IOException {
// Do some stuff ...
response.setContentType("text/csv");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=\"export_streets.csv\"");
this.exportService.exportStreetsToCsv(toExport, response.getWriter());
}
public void exportStreetsToCsv(Set<Street> streets, PrintWriter writer) throws IOException {
writer.print('\ufeff'); // Write BOM
CSVFormat csvFormat = CSVFormat.EXCEL.withQuoteMode(QuoteMode.ALL).withDelimiter(';');
CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat);
// Print records
csvPrinter.flush();
csvPrinter.close();
}
const blobFile = new Blob([response.data], { type: 'text/csv' });
this.FileSaver.saveAs(blobFile, 'test.csv');
I managed to make it work by adding BOM before saving the file, but it's an ugly fix that I'd like to avoid. Plus, for some reason, with that fix the first line of my CSV file has double quotes. Here's the fix:
const blobFile = new Blob([new Uint8Array([0xEF, 0xBB, 0xBF]), response.data], { type: 'text/csv;charset=utf-8' });
I didn't do much to fix my issue, and I'm still not sure what was wrong. I only had to change the PrintWriter
to a Writer
, and add the charset in my javascript code.
public void exportStreetsToCsv(Set<Street> streets, Writer writer) throws IOException {
writer.write('\uFEFF'); // Write BOM
// ...
const blobFile = new Blob([response.data], { type: 'text/csv;charset=utf-8' });
this.FileSaver.saveAs(blobFile, 'test.csv');