wkhtmltopdf介紹
wkhtmltopdf是一款安裝在服務端的pdf導出插件,隻需要通過指令行就能調用,将html檔案轉換成pdf檔案;
使用這款插件,java程式中不需要額外引入任何依賴。
使用前準備
去官網【https://wkhtmltopdf.org/】下載下傳安裝插件
使用方法
一、控制台簡單使用
- 準備好一個用來導出的html檔案
- 打開插件安裝的目錄,并在此處打開控制台視窗
/**
* 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);
}
}
}