项目中遇到了导出pdf的问题,一开始采用ireport的形式,但是这东西他不兼容jdk1.8所以就放弃了,有没有什么好的方法直接将excel转成pdf输出呢?我也是在网上白嫖了一顿。
Aspose-Cells.jar他就来了。
只需要将jar包和去水印的license文件导入到项目中,再写几行代码就可以了。
相关jar包已经放到了网盘中,移步下载。
链接:下载jar包
提取码:dpak
import com.aspose.cells.*;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
/**
* excel转pdf
* @description:xlsx转pdf
*/
public class ExcelToPdf {
/**
* 获取license 去除水印
* @return
*/
public static boolean getLicense() {
boolean result = false;
try {
InputStream is = XLSXConvertToPDF.class.getClassLoader().getResourceAsStream("\\license.xml");
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* excel 转为pdf 输出。
*
* @param sourceFilePath excel文件
* @param desFilePathd pad 输出文件目录
*/
public static void excel2pdf(String sourceFilePath, String desFilePathd){
if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
return;
}
try {
Workbook wb = new Workbook(sourceFilePath);// 原始excel路径
FileOutputStream fileOS = new FileOutputStream(desFilePathd);
PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
pdfSaveOptions.setOnePagePerSheet(true);//如果需要分页打印的话需要注释此行
//pdfSaveOptions.setAllColumnsInOnePagePerSheet(true);
//如果 AllColumnsInOnePagePerSheet 为 true ,
//则结果中一张表的所有列内容将仅输出到一页 宽度会被失效,
//这样所有的列就都可以显示在每一页中,不会被截断了
int[] autoDrawSheets={3};
//当excel中对应的sheet页宽度太大时,在PDF中会拆断并分页。此处等比缩放。
autoDraw(wb,autoDrawSheets);
int[] showSheets={0};
//隐藏workbook中不需要的sheet页。
printSheetPage(wb,showSheets);
wb.save(fileOS, pdfSaveOptions);
fileOS.flush();
fileOS.close();
//System.out.println("转换PDF完毕!");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 设置打印的sheet 自动拉伸比例
* @param wb
* @param page 自动拉伸的页的sheet数组
*/
public static void autoDraw(Workbook wb,int[] page){
if(null!=page&&page.length>0){
for (int i = 0; i < page.length; i++) {
wb.getWorksheets().get(i).getHorizontalPageBreaks().clear();
wb.getWorksheets().get(i).getVerticalPageBreaks().clear();
}
}
}
/**
* 隐藏workbook中不需要的sheet页。
* @param wb
* @param page 显示页的sheet数组
*/
public static void printSheetPage(Workbook wb,int[] page){
for (int i= 1; i < wb.getWorksheets().getCount(); i++) {
wb.getWorksheets().get(i).setVisible(false);
}
if(null==page||page.length==0){
wb.getWorksheets().get(0).setVisible(true);
}else{
for (int i = 0; i < page.length; i++) {
wb.getWorksheets().get(i).setVisible(true);
}
}
}
}
下面测试:
@Test void toPdf() { String path1 = "D:/pdfLoc/test.xlsx"; //现存的excel文件全路径 + 文件名 + 后缀 String path2 = "D:/pdfLoc/test.pdf"; //要生成的pdf文件全路径 + 文件名 + 后缀 ExcelToPdf.excel2pdf(path1,path2); }
效果图,随便写的,没搞样式,大家根据自己需求来。
那么如何输出到浏览器下载呢?
此时已经知道了生成的pdf地址。
后端:
response.setHeader("Content-Type", "application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-disposition", "attachment;filename*="+ URLEncoder.encode(fileName,"UTF-8"));//默认Excel名称
response.setHeader("Access-Control-Expose-Headers", "Content-disposition");
OutputStream os = response.getOutputStream();
FileInputStream stream = new FileInputStream("D:/pdfLoc/test.pdf");//读取生成好的pdf
byte[] buffer = new byte[4096];
int n = 0;
while (-1 != (n = stream.read(buffer))) {
os.write(buffer, 0, n);
}
stream.close();
os.flush();
os.close();
//只是列了这几行关键代码,具体业务具体分析
前端处理:
axios({ // 用axios发送post请求
method: 'post',
url: _api, // 请求地址
data: _param, // data参数
responseType: 'arraybuffer', // 表明返回服务器返回的数据类型
headers: { //
'Content-Type': 'application/json;charset=utf-8'
},
// 表明返回服务器返回的数据类型
}).then((res) => {
//console.log('headers', res.headers)
let fileName = decodeURI(res.headers['content-disposition'].split('=')[1]);
let url = window.URL.createObjectURL(new Blob([res.data], { type: 'application/pdf' }))
const a = document.createElement('a')
a.style.display = 'none'
a.download = fileName
a.href = url
a.click()
if (document.body.contains(a)) {
document.body.removeChild(a)
}
}).catch(function(error) {
console.log("下载失败!");
});
这样一套组合拳下来,基本就出来了。