java项目使用wkhtmltopdf实现模板导出pdf
wkhtmltopdf介绍
wkhtmltopdf是一款安装在服务端的pdf导出插件,只需要通过命令行就能调用,将html文件转换成pdf文件;
使用这款插件,java程序中不需要额外引入任何依赖。
使用前准备
去官网【https://wkhtmltopdf.org/】下载安装插件
使用方法
一、控制台简单使用
-
准备好一个用来导出的html文件
-
打开插件安装的目录,并在此处打开控制台窗口
-
在控制台输入命令 .\wkhtmltopdf.exe {html文件的地址} {要导出的地址}
导出成功!
二、整合java程序使用
在我的项目中使用了freemarker将ftl网页模板文件与数据绑定,生成html文件,然后再调用wkhtmltopdf生成pdf文件
话不多说,直接上代码
/**
* HTML转PDF工具类(WK实现,样式更完善)
*
* @author wangmeng
* @since 2021/7/15
*/
@Slf4j
public class Html2PdfUtils {
/**
* 根据模板导出pdf文件(A4尺寸)
*
* @param templateName 模板名称
* @param data 用来渲染的页面数据
* @param savePath 导出路径
* @param fileName pdf名称
*/
public static void makePdf(String templateName, Object data, String savePath, String fileName) {
makePdf(templateName, data, savePath, fileName, PageSize.defaultSize);
}
/**
* 根据模板导出pdf文件
*
* @param templateName 模板名称
* @param data 用来渲染的页面数据
* @param savePath 导出路径
* @param fileName pdf名称
* @param pageSize 页面尺寸
*/
public static void makePdf(String templateName, Object data, String savePath, String fileName, PageSize pageSize) {
FileUtils.createFileFolder(savePath);
String htmlData = getContent(templateName, data);
try {
createPdf(htmlData, savePath, fileName, pageSize);
} catch (Exception e) {
log.error(e.getMessage());
throw new CustomException("导出pdf文件失败!");
}
}
/**
* 获取pdf模板
*
* @param templateName 模板名称
* @param data 用来渲染的页面数据
* @return 渲染后的页面
*/
private static String getContent(String templateName, Object data) {
if (StringUtils.isBlank(templateName)) {
throw new CustomException("模板路径和模板名称不能为空!");
}
//使用数据渲染模板
try (StringWriter writer = new StringWriter()) {
//FreeMarker配置
Configuration config = new Configuration(Configuration.VERSION_2_3_25);
config.setDefaultEncoding("UTF-8");
config.setDirectoryForTemplateLoading(new File(ConfigUtils.getPdfTemplatePath())); //设置读取模板的目录
config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
config.setLogTemplateExceptions(false);
Template template = config.getTemplate(templateName);//根据模板名称 获取对应模板
template.process(data, writer);
writer.flush();
return writer.toString();
} catch (IOException | TemplateException ioException) {
log.error(ioException.getMessage());
throw new CustomException(GlobalI18nConstant.TEMPLATE_ERROR);
}
}
/**
* 根据html文件生成pdf
*
* @param htmlContent html
* @param savePath 导出路径
* @param fileName 文件名
* @param pageSize 尺寸
* @throws IOException
*/
private static void createPdf(String htmlContent, String savePath, String fileName, PageSize pageSize) throws IOException {
//创建临时文件夹,存放渲染完的html文件
String time = DateUtils.toString(new Date(), DateUtils.YYYY_MM_DD_HH_MM_SS3);
String tempPath = ConfigUtils.getBaseDir() + ConfigUtils.getBaseTempDir() + File.separator + time + IdUtils.uuid();
FileUtils.createFileFolder(tempPath);
FileOutputStream fileoutputstream = null;
String space = GlobalConstant.SPACE;
//临时文件名,防止文件名中带空格
String tempFileName = IdUtils.uuid() + ".pdf";
try {
File tempHtml = new File(tempPath + File.separator + "temp.html");
fileoutputstream = new FileOutputStream(tempHtml);
fileoutputstream.write(htmlContent.getBytes(StandardCharsets.UTF_8));
StringBuilder cmd = new StringBuilder();
cmd.append(ConfigUtils.getWkhtmltopdf()).append(space);
//优先枚举尺寸类型
if (pageSize.getSize() != null) {
cmd.append("--page-size").append(space).append(pageSize.getSize());
} else {
cmd.append("--page-width").append(space).append(pageSize.getWidth()).append(space)
.append("--page-height").append(space).append(pageSize.getHeight());
}
// 若PDF有图片标签 下载SRC路径地址下的图片
cmd.append(space).append("--image-quality 94");
cmd.append(space).append(tempPath).append(File.separator).append("temp.html").append(space).append(savePath).append(File.separator).append(tempFileName);
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(cmd.toString());
proc.waitFor();
//修改文件名
File pdf = new File(savePath + File.separator + tempFileName);
File newFile = new File(pdf.getParent() + File.separator + fileName);
int i = 1;
int index = fileName.lastIndexOf(".");
String prefix = fileName.substring(0, index);
String suffix = fileName.substring(index);
while (newFile.exists()) {
newFile = new File(pdf.getParent() + File.separator + prefix + '(' + i + ')' + suffix);
i++;
}
if (!pdf.renameTo(newFile)) {
throw new CustomException("文件重命名失败!");
}
} catch (Exception e) {
log.error(e.getMessage());
} finally {
if (fileoutputstream != null) {
fileoutputstream.close();
}
//删除临时文件夹
FileUtils.deleteDirectory(tempPath);
}
}
}
我的方法整合了设置页面尺寸,导出图片功能,除此之外wkhtmltopdf还有更多骚操作等待大家发现,想要了解就立即打开官网吧