最近有一个需求,需要根据excel模板PDF报表;需要先根据excel模板生成excel文件,再由excel生成pdf文件,最后下载功;
生成excel报表
使用
easypoi
组件,详细可参考文档中excel模板部分;
使用方法概述
该方式的优势为样式与模板样式完全一致,可以实现单值属性与列表遍历;
- 在excel模板中修改单元格内容为相应的
easypoi
支持的表达式; - 定义
TemplateParam
(模板属性)和数据属性; - 调用静态方法:
ExcelExportUtil.exportExcel
excel生成PDF报表
实现方式种类
IText
纯JAVA实现的PDF生成方法,跨平台,缺点也很明显:API比较难用,同时很难处理Excel的样式;
OpenOffice
-
导入jar包: com.artofsolving-jodconverter
-
openOffice监听端口:
soffice.exe -headless -accept="socket,host=%s,port=%s;urp;" -nofirststartwizard
-
使用openOffice转换为PDF
//连接
var conn = new SocketOpenOfficeConnection(hostname,port);
conn.connect();
//转换
converter = new OpenOfficeDocumentConverter(conn);
converter.convert(docFile,pdfFile);
//关闭连接
conn.disconnect();
优势: 跨平台;
缺点: openOffice转换成的PDF在一定程度失真,比如excel边框自动加粗等,某一些样式不支持等,但是linux服务器上的唯一选择.
windowOffice 或 wps
-
导入jar包: jacob-1.19.zip
-
安装windowOffice或wps;
-
转换:
//office命令
ActiveXComponent app = new ActiveXComponent("Excel.Application");
//Wps方式
app = new ActiveXComponent("KET.Application");
app.setProperty("Visible", false);
Dispatch excels = app.getProperty("Workbooks").toDispatch();
excel = Dispatch.call(excels, "Open", path, false, true).toDispatch();
Dispatch.call(excel, "ExportAsFixedFormat", 0, pdfAbsPath);
优点: 完美的样式;
缺点: 仅支持window服务器;
文件下载
后端下载基础代码
response.setCharacterEncoding(CharsetUtil.UTF_8);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition","attachment; filename=" + fileName);
response.setContentLengthLong(pdfFile.length());
注意事项
- 不同浏览器支持的文件名编码格式不同,大部分使用UrlEnocde编码即可,safari浏览器需要ISO8859-1的字符串编码
前端处理
前端使用js下载blob,并创建blob的下载地址
config.responseType = "blob";
let blob = new Blob([response.data],{type: 'application/pdf'}); //创建一个blob对象
let downloadName = response.headers["content-disposition"].split(";")[1].split("filename=")[1];
let a = document.createElement('a');
let url = URL.createObjectURL(blob)
a.href = url; // response is a blob
a.download = downloadName; //文件名称
a.style.display = 'none';
document.body.appendChild(a);
a.click();
a.remove();
缺点: 在safari中出现下载文件名为:known的异常;
使用第三方组件
该方法是上一种方法的扩展,不自己创建a标签,使用file-sever组件,只需要传入blob对象即可;
FileSaver.saveAs(blob, downloadName);
缺点: 在safari中出现下载文件名为:known的异常;
前端创建真实的后端下载地址
let a = document.createElement('a');
a.href = url; // 直接为后端的url;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
a.remove();
优点:理论上所有浏览器均可正确识别文件名信息;
缺点: 因为不是通过ajax请求的后端接口,在前后端分离系统中要单独处理权限验证的东西(如token等);