2017-09-19 2 views
1

Apparemment, pour exceller dans l'ouverture des fichiers CSV, il devrait avoir le Byte Order Mark au début. Le téléchargement de CSV est implémenté en écrivant dans le flux de sortie HttpServletResponse dans le contrôleur, car les données sont générées pendant la requête. Je reçois une exception lorsque j'essaie d'écrire les octets de la nomenclature - java.io.CharConversionException: Not an ISO 8859-1 character: [] (même si l'encodage que j'ai spécifié est UTF-8).Java Spring renvoyant le fichier CSV encodé en UTF-8 avec BOM


La méthode du contrôleur en question

@RequestMapping("/monthly/list") 
public List<MonthlyDetailsItem> queryDetailsItems(
     MonthlyDetailsItemQuery query, 
     @RequestParam(value = "format", required = false) String format, 
     @RequestParam(value = "attachment", required = false, defaultValue="false") Boolean attachment, 
     HttpServletResponse response) throws Exception 
{ 
    // load item list 
    List<MonthlyDetailsItem> list = detailsSvc.queryMonthlyDetailsForList(query); 
    // adjust format 
    format = format != null ? format.toLowerCase() : "json"; 
    if (!Arrays.asList("json", "csv").contains(format)) format = "json"; 

    // modify common response headers 
    response.setCharacterEncoding("UTF-8"); 
    if (attachment) 
     response.setHeader("Content-Disposition", "attachment;filename=duomenys." + format); 

    // build csv 
    if ("csv".equals(format)) { 
     response.setContentType("text/csv; charset=UTF-8"); 
     response.getOutputStream().print("\ufeff"); 
     response.getOutputStream().write(buildMonthlyDetailsItemCsv(list).getBytes("UTF-8")); 
     return null; 
    } 

    return list; 
} 
+0

Pourriez-vous essayer 'response.getOutputStream(). Write (" \ ufeff ".getBytes (" UTF-8 "));' pour la partie BOM? – Berger

Répondre

0

Il ne fait pas beaucoup de sens: la nomenclature est UTF-16; il n'y a pas d'ordre des octets avec UTF-8. L'encodage que vous avez défini avec setCharacterEncoding est utilisé pour getWriter, pas pour getOutputStream.

MISE À JOUR:

OK, essayez ceci:

if ("csv".equals(format)) { 
    response.setContentType("text/csv; charset=UTF-8"); 
    PrintWriter out = response.getWriter(); 
    out.print("\uFEFF"); 
    out.print(buildMonthlyDetailsItemCsv(list)); 
    return null; 
} 

Je suppose que la méthode buildMonthlyDetailsItemCsv renvoie une chaîne.

+0

Ce n'est pas vrai. Voir https://en.wikipedia.org/wiki/Byte_order_mark. Une nomenclature est définie pour UTF-8 mais elle n'est pas obligatoire. Hélas, Java n'est pas capable de gérer automatiquement les nomenclatures UTF-8. – vanje

+0

@vanje Eh bien, c'est inutile avec l'encodage UTF-8. –

+0

Oui peut-être. Mais ce n'est pas le point. Parfois, vous devez faire avec. Inutile ou pas. – vanje