最近遇到一个问题,java接口返回一个pdf文件,浏览器直接预览,但是预览时显示的文件名称不是在响应头中设置的filename值。
一、问题
未改动代码 测试Controller:
@RequestMapping("preview")
public void preview(HttpServletResponse response) {
try {
byte[] pdfByte = getTestFile(); //从本地读取一个pdf文件做测试
String pdfName = "自定义PDF标题";
response.reset();
response.setContentType("application/pdf;charset=UTF-8");
response.setHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(pdfName, "UTF-8"));//这里的名字并不起作用
OutputStream out = response.getOutputStream();
out.write(pdfByte);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
我这里使用了用chrome浏览器测试,这时自定义的标题并不会被显示,显示为请求名称,或者文件名字(这个文件名字与我们在本地磁盘上看到的文件名不一定相同)
二、原因
pdf文件用编辑器打开,可以查看文档属性,我这里用了wps。
对比可以看出,文档属性中的这个标题属性才是被浏览器显示的标题,这个属性为空就会显示为请求名。并且这个标题属性跟磁盘上看到的文件名没有关系。所以想修改预览时的文件名,应该是更改这个属性才可以。
三、解决
有个这个方向,我搜索了一些方法,成功了一个,就是利用pdfbox这个工具,可能还有其他的好方法,暂时没有想到。
一、首先引入工具jar的maven依赖
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.19</version>
</dependency>
二、修改代码
@RequestMapping("preview")
public void preview(HttpServletResponse response) {
try {
byte[] pdfByte = getTestFile(); //从本地读取一个pdf文件做测试
String pdfName = "自定义PDF标题";
response.reset();
response.setContentType("application/pdf;charset=UTF-8");
response.setHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(pdfName, "UTF-8"));//这里的名字并不起作用
OutputStream out = response.getOutputStream();
PDDocument document = PDDocument.load(pdfByte); //加载pdf
PDDocumentInformation info = document.getDocumentInformation(); //获得文档属性对象
info.setTitle(pdfName); //修改标题属性 这个标题会被展示
document.setDocumentInformation(info);
document.save(out); //修改完直接输出到响应体中
document.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
对比原来的代码,就是在文件流写入响应体之前,经过一下pdfbox,修改标题属性,然后pdfbox的save方法可以直接写入到响应体中。
再次测试:
可以看到自定义标题已经生效了。问题解决~