Java下载Excel表名显示波浪号失效


     遇到一个需求,需要完成下载Excel表格的功能,表格名包含 “~” 符号,开发时是按照"~" 写的,但是运行的效果却是 “_”,因为项目无法在本地启动,无法 debug,需要重新搭一个简单demo 在本地调试。
     使用的是 SpringBoot 框架,快速构建。

一、SpringBoot 构建 Restful Web 服务

     先在pom中添加父节点:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
    </parent>

再导入 SpringBoot Web 依赖:

<dependencies> 
	<dependency> 
		<groupId>org.springframework.boot</groupId> 
		<artifactId>spring-boot-starter-web</artifactId> 
	</dependency> 
</dependencies>

写个最简单的启动类,注意必须把类放置在包下:

package demo.restful;
@SpringBootApplication
@RestController
public class RestfulDemo {
    public static void main(String[] args) {
        SpringApplication.run(RestfulDemo.class,args);
    }

    @GetMapping("/hellodemo")
    public String hello(){
        return "hello";
    }
}

     访问 http://localhost:8080/hellodemo 即可。
    

二、使用 POI 生成 Excel

     需求中点击数据看板的“下载”按钮后,执行下载功能,使用的是 HTTP的 GET 方法,而且需要用到 response 的 setHeader 方法。思路是使用 POI 接口,生成 Excel 文件,然后将其写入文件流。写个最简单的生成表格demo:

@SpringBootApplication
@RestController
public class RestfulDemo {
    public static void main(String[] args) {
        SpringApplication.run(RestfulDemo.class, args);
    }

    @GetMapping("/hellodemo")
    public String hello(HttpServletResponse response) throws IOException {

        HSSFWorkbook wb = new HSSFWorkbook();//创建HSSFWorkbook对象
        HSSFSheet sheet = wb.createSheet("成绩表");//建立sheet对象
        HSSFRow row1 = sheet.createRow(0); //在sheet里创建第一行,参数为行索引
        HSSFCell cell = row1.createCell(0); //创建单元格
        cell.setCellValue("学生成绩表");        //设置单元格内容

        //合并单元格 CellRangeAddress构造参数依次表示起始行,截止行,起始列, 截止列
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 3));

        //在sheet里创建第二行
        HSSFRow row2 = sheet.createRow(1);

        //创建单元格并设置单元格内容
        row2.createCell(0).setCellValue("姓名");
        row2.createCell(1).setCellValue("班级");
        row2.createCell(2).setCellValue("语文成绩");
        row2.createCell(3).setCellValue("数学成绩");
        row2.createCell(4).setCellValue("英语成绩");

        //在sheet里创建第三行
        HSSFRow row3 = sheet.createRow(2);
        row3.createCell(0).setCellValue("小明");
        row3.createCell(1).setCellValue("1班");
        row3.createCell(2).setCellValue(80);
        row3.createCell(3).setCellValue(75);
        row3.createCell(4).setCellValue(88);

        HSSFRow row4 = sheet.createRow(3);
        row4.createCell(0).setCellValue("小红");
        row4.createCell(1).setCellValue("1班");
        row4.createCell(2).setCellValue(82);
        row4.createCell(3).setCellValue(70);
        row4.createCell(4).setCellValue(90);

        //输出Excel文件
        OutputStream output = response.getOutputStream();
        response.reset();

        //设置响应头
        response.setHeader("Content-disposition", "attachment; filename=Student~1.xls");
        response.setContentType("application/msexcel");

        wb.write(output);
        output.close();
        return "hello";
    }
}

(这里先设置了表格的列名和数据,再获取响应的输出流,然后设置响应头、然后对它进行写操作,)
     可以看到,表名应该是 Student~1.xls,运行代码,效果如下:
在这里插入图片描述
     问题出现了❗ 响应头里设置成了 “~”,但是实际下载的却是"_"。
    对响应的设置主要是:
    response.setContentType(MIME) 的作用是使客户端浏览器,区分不同种类的数据,并根据不同的 MIME 调用浏览器内不同的程序嵌入模块来处理相应的数据。
在这里插入图片描述
    Excel 文件对应的是 application/msexcel,没什么问题。
     主要是响应头的设置,换些形式:

 String fileName = "起始日期~终止日期";
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("GBK"), "ISO-8859-1") + ".xls");

结果:
在这里插入图片描述

  response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1") + ".xls");

在这里插入图片描述

response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName,"UTF-8")+ ".xls");

在这里插入图片描述

response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName,"GBK")+ ".xls");

在这里插入图片描述
连文件名也变得离谱了起来。

  response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + URLEncoder.encode(fileName,"UTF-8")+ ".xls");

在这里插入图片描述
    整了一圈,还是显示失效。
    看了一下 RFC 关于字符集和语言编码的说明 https://www.rfc-editor.org/rfc/rfc5987.txt,说是 header 不能携带 ISO-8859-1 字符集之外的类型
    但是前面为什么不直接使用 “中文文件名”.getBytes(“ISO8859-1”); 这样的代码呢?因为在 ISO8859-1 的编码表中,根本就没有汉字字符,所以应该先通过 “中文文件名”.getBytes(“utf-8”) 获取其 byte[] 字节,让其按照字节来编码,即再使用 new String(“中文文件名”.getBytes(“utf-8”), “ISO8859-1”) 将其重新组成一个字符串:

  response.setHeader("Content-Disposition", "attachment;filename=" + new String((tableName + "~" + ".xlsx").getBytes(), StandardCharsets.ISO_8859_1));

    然而还是显示不来波浪线,有待解决。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值