WWF世界自然基金会 2025-11-16 21:55 采纳率: 98.8%
浏览 1
已采纳

Spring Boot导出报告时中文乱码如何解决?

在使用Spring Boot导出Excel或PDF报告时,常因响应头未正确设置字符编码导致中文乱码。典型问题出现在Controller返回文件流时,未指定`Content-Type`为`application/vnd.ms-excel;charset=UTF-8`,且未通过`URLEncoder`对文件名进行编码处理。尤其在Nginx代理或不同浏览器环境下,中文文件名更易出现乱码。此外,数据本身若未以UTF-8编码写入输出流,也会导致内容乱码。需综合配置响应头、文件名编码及IO流字符集,方可彻底解决。
  • 写回答

2条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-11-16 23:19
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案能帮助您,请采纳,非常感谢!
    .
    每日一句正能量,让它带给您好心情:别让别人的评价,左右你的人生,你才是自己的主角。
    .

    在Spring Boot中解决导出报告时的中文乱码问题,需要从响应头设置、文件名编码和数据流编码三个方面进行综合处理。以下是具体的解决方案:

    1. 设置正确的响应头

    Excel文件导出

    @RestController
    public class ReportController {
        
        @GetMapping("/export/excel")
        public ResponseEntity<byte[]> exportExcel(HttpServletResponse response) {
            try {
                // 设置响应头
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.parseMediaType("application/vnd.ms-excel;charset=UTF-8"));
                
                // 文件名编码处理
                String fileName = URLEncoder.encode("中文报告.xlsx", "UTF-8");
                headers.setContentDispositionFormData("attachment", fileName);
                headers.setCacheControl("no-cache");
                
                // 生成Excel数据
                byte[] excelData = generateExcelData();
                
                return new ResponseEntity<>(excelData, headers, HttpStatus.OK);
            } catch (Exception e) {
                return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
            }
        }
    }
    

    PDF文件导出

    @GetMapping("/export/pdf")
    public ResponseEntity<byte[]> exportPdf() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("application/pdf;charset=UTF-8"));
        
        String fileName = URLEncoder.encode("中文报告.pdf", "UTF-8");
        headers.setContentDispositionFormData("attachment", fileName);
        
        byte[] pdfData = generatePdfData();
        return new ResponseEntity<>(pdfData, headers, HttpStatus.OK);
    }
    

    2. 兼容不同浏览器的文件名编码

    public static String encodeFileName(HttpServletRequest request, String fileName) {
        try {
            String userAgent = request.getHeader("User-Agent");
            String encodedFileName;
            
            if (userAgent != null && userAgent.contains("MSIE")) {
                // IE浏览器
                encodedFileName = URLEncoder.encode(fileName, "UTF-8");
            } else if (userAgent != null && userAgent.contains("Firefox")) {
                // Firefox浏览器
                encodedFileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
            } else {
                // 其他浏览器(Chrome、Safari等)
                encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            }
            
            return encodedFileName;
        } catch (UnsupportedEncodingException e) {
            return fileName;
        }
    }
    

    3. 确保数据流使用UTF-8编码

    使用Apache POI导出Excel

    private byte[] generateExcelData() throws IOException {
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("报告");
        
        // 创建支持中文的字体
        Font chineseFont = workbook.createFont();
        chineseFont.setFontName("宋体");
        chineseFont.setCharSet(Font.DEFAULT_CHARSET);
        
        // 创建单元格样式
        CellStyle style = workbook.createCellStyle();
        style.setFont(chineseFont);
        
        // 写入中文数据
        Row row = sheet.createRow(0);
        Cell cell = row.createCell(0);
        cell.setCellValue("中文内容测试");
        cell.setCellStyle(style);
        
        // 输出到字节数组
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        workbook.write(outputStream);
        workbook.close();
        
        return outputStream.toByteArray();
    }
    

    使用iText导出PDF

    private byte[] generatePdfData() throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        Document document = new Document();
        PdfWriter.getInstance(document, outputStream);
        
        document.open();
        
        // 设置中文字体
        BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
        Font chineseFont = new Font(baseFont, 12, Font.NORMAL);
        
        // 写入中文内容
        document.add(new Paragraph("中文报告内容", chineseFont));
        document.add(new Paragraph("测试数据:中文显示正常", chineseFont));
        
        document.close();
        return outputStream.toByteArray();
    }
    

    4. 全局配置解决字符编码问题

    在application.yml中配置

    spring:
      servlet:
        encoding:
          charset: UTF-8
          enabled: true
          force: true
      http:
        encoding:
          charset: UTF-8
          enabled: true
          force: true
    

    配置CharacterEncodingFilter

    @Configuration
    public class EncodingConfig {
        
        @Bean
        public FilterRegistrationBean<CharacterEncodingFilter> characterEncodingFilter() {
            FilterRegistrationBean<CharacterEncodingFilter> filter = new FilterRegistrationBean<>();
            filter.setFilter(new CharacterEncodingFilter());
            filter.addInitParameter("encoding", "UTF-8");
            filter.addInitParameter("forceEncoding", "true");
            filter.addUrlPatterns("/*");
            return filter;
        }
    }
    

    5. Nginx代理服务器配置

    如果使用Nginx作为反向代理,需要在配置文件中添加字符编码设置:

    server {
        listen 80;
        server_name your-domain.com;
        
        charset utf-8;
        
        location / {
            proxy_pass http://spring-boot-app;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            
            # 确保字符编码正确传递
            proxy_set_header Accept-Encoding "";
        }
    }
    

    总结

    解决Spring Boot导出中文乱码问题的关键步骤:

    1. 设置正确的Content-Type:包含字符编码信息
    2. 文件名编码处理:使用URLEncoder对中文文件名进行编码
    3. 数据流编码:确保输出流使用UTF-8编码
    4. 浏览器兼容:针对不同浏览器采用相应的编码策略
    5. 代理服务器配置:确保Nginx等代理服务器正确传递字符编码

    通过以上综合措施,可以有效解决Spring Boot导出报告时的中文乱码问题。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 已采纳回答 11月17日
  • 创建了问题 11月16日