在 Java 中发送 BOM 以 UTF-8 编码的 CSV 文件
Send CSV file encoded in UTF-8 with BOM in Java
我正在编写一个 CSV 文件,其中包含一些重音符号,以 UTF-8 编码。问题是当我尝试用 Excel 打开文件时,内容仍然是乱七八糟的。我必须使用 Sublime Text 打开我的文件并将其保存在 "UTF-8 with BOM" 中才能获得正确的文件(将文件保存为简单的 UTF-8 不起作用)。我阅读了许多 SO 问题并尝试应用解决方案,但其中 none 有效。我不知道这是我写文件时的后端问题,还是下载时的前端问题。
Spring 控制器
@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');
我设法通过在保存文件之前添加 BOM 使其工作,但这是一个我想避免的丑陋修复。另外,出于某种原因,修复后我的 CSV 文件的第一行有双引号。这是修复:
const blobFile = new Blob([new Uint8Array([0xEF, 0xBB, 0xBF]), response.data], { type: 'text/csv;charset=utf-8' });
我没有做太多事情来解决我的问题,我仍然不确定哪里出了问题。我只需要将 PrintWriter
更改为 Writer
,并在我的 javascript 代码中添加字符集。
后端服务
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');
我正在编写一个 CSV 文件,其中包含一些重音符号,以 UTF-8 编码。问题是当我尝试用 Excel 打开文件时,内容仍然是乱七八糟的。我必须使用 Sublime Text 打开我的文件并将其保存在 "UTF-8 with BOM" 中才能获得正确的文件(将文件保存为简单的 UTF-8 不起作用)。我阅读了许多 SO 问题并尝试应用解决方案,但其中 none 有效。我不知道这是我写文件时的后端问题,还是下载时的前端问题。
Spring 控制器
@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');
我设法通过在保存文件之前添加 BOM 使其工作,但这是一个我想避免的丑陋修复。另外,出于某种原因,修复后我的 CSV 文件的第一行有双引号。这是修复:
const blobFile = new Blob([new Uint8Array([0xEF, 0xBB, 0xBF]), response.data], { type: 'text/csv;charset=utf-8' });
我没有做太多事情来解决我的问题,我仍然不确定哪里出了问题。我只需要将 PrintWriter
更改为 Writer
,并在我的 javascript 代码中添加字符集。
后端服务
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');