html pdf 模板,记一次 HTML 模板 转 PDF

HTM模板的样式和实际转pdf样式会有非常大的差距 获取模板的方式也是十分曲折...

这里记录一下便捷的方式

第一步:

bVbxJG1?w=1474&h=914

在前端调用windows的打印页面 这里的样式完全和html一一致;左侧 目标打印机 选择:另存为PDF

这里保存的pdf样式和html的样式完全一致。

第二步:

把上一步保存好的pdf转换为word 在线转换地址 pdf2word

第三步:

把上一步保存好的word转换为html 在线转换地址 word2html

获得的模板在稍作调整即可

我是这么转换了几次才得到了样式最贴近的模板

如果样式差距大 可以自己调整转换的步骤 省略 or 多转几次

jar包中有default.css文件可能会影响样式

bVbxJKw?w=421&h=81

图片支持http链接 直接像普通的字符串一样扔进去就可以

如果样式难搞 字段不多建议使用 pdf模板转换 样式不会改变 缺点:字符长度完全受域限制 图片插入太费劲

首先引入依赖

com.itextpdf.tool

xmlworker

5.5.13

com.itextpdf

itextpdf

5.5.9

com.itextpdf

itext-asian

5.2.0

以下为批量导出的代码 忽略业务代码

@RequestMapping(value="/exportPrintList")

public void exportPdf(String keyword, String status, String createStartTime, String createEndTime, HttpServletResponse response) {

FileUtil.createDir(pdfFilePath,false);

//业务代码 查询需要导出的数据

AppHealthtestEx ahe = new AppHealthtestEx();

ahe.setType(HealthTestType.HealthTest.getType());

ahe.setKeywords(keyword);

ahe.setCreateStartTime(createStartTime);

ahe.setCreateEndTime(createEndTime);

if (StringUtils.isNotBlank(status)) {

ahe.setStatus(Integer.parseInt(status));

}

ahe.setOrgOid(getSearchOrgOid());

List testNumbers = service.findPrintHealthtestEx(ahe);

int corePoolSize = 5;

if(testNumbers.size()

corePoolSize = testNumbers.size();

}

if(corePoolSize>10){

corePoolSize = 10;

}

// 批量导出 多个任务

ExecutorService executorService = new ThreadPoolExecutor(corePoolSize, testNumbers.size(), 0L,

TimeUnit.SECONDS, new ArrayBlockingQueue<>(3));

List result = Lists.newArrayList();

AppPrintMode findPrintMode = new AppPrintMode();

List appPrintModes = appPrintModeService.find(findPrintMode);

if(CollectionUtils.isNotEmpty(appPrintModes)){

findPrintMode = appPrintModes.get(0);

}

int printMode = 1;

if(findPrintMode.getPrintPlateType()!=null){

printMode = findPrintMode.getPrintPlateType();

}

String template = "";

if(printMode == 1){

template = templatePath+"PrintAll.html";

}else{

template = templatePath +"PrintConcis.html";

}

for (AppHealthtestEx ex : testNumbers) {

result.add(executorService.submit(new

PrintThread(pdfFilePath,ex.getTestNumber(),service,template,ex.getName())));

}

executorService.shutdown();

try {

executorService.awaitTermination(600,TimeUnit.SECONDS);

FileUtil.compressToZip(pdfFilePath,filePath,"体检报告导出.zip");

service.downloadPdf(response, "体检报告导出.zip");

}catch (Exception e){

log.error("export pdf error :",e);

}

}

线程类:

import com.itextpdf.text.Document;

import com.itextpdf.text.PageSize;

import com.itextpdf.text.pdf.PdfWriter;

import com.itextpdf.tool.xml.XMLWorkerHelper;

import com.itextpdf.tool.xml.html.CssAppliers;

import com.itextpdf.tool.xml.html.CssAppliersImpl;

import com.itextpdf.tool.xml.html.Tags;

import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;

import org.apache.commons.collections.MapUtils;

import org.apache.commons.lang3.StringUtils;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.nio.charset.Charset;

import java.util.Map;

import java.util.concurrent.Callable;

public class PrintThread implements Callable{

public Logger log = LoggerFactory.getLogger(this.getClass());

private String fileFilePath;

private String testNumber;

private String templatePath;

private AppHealthtestService appHealthtestService;

private String fileName;

public PrintThread(String fileFilePath, String testNumber, AppHealthtestService appHealthtestService,String templatePath,String fileName) {

this.fileFilePath = fileFilePath;

this.testNumber = testNumber;

this.appHealthtestService = appHealthtestService;

this.templatePath = templatePath;

this.fileName = fileName;

}

@Override

public Object call(){

FileOutputStream fos = null;

Document document = null;

try {

// 获取所有占位符对应的值

Map stringObjectMap = appHealthtestService.exportPreview(testNumber);

String htmlContent = htmlSetValue(readString(templatePath),stringObjectMap);

ByteArrayInputStream in = new ByteArrayInputStream(htmlContent.getBytes("UTF-8"));

document = new Document(PageSize.A4);

PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(fileFilePath+ fileName+testNumber + ".pdf"));

document.open();

document.addTitle("xxx报告");

// 使用我们的字体提供器,并将其设置为unicode字体样式

AsianFontProvider fontProvider = new AsianFontProvider();

fontProvider.addFontSubstitute("lowagie", "garamond");

// 生产环境是windows 我本地也是windows 如果不加这句 在我本地是没问题 在服务器上就是乱码 ... 坑

fontProvider.setUseUnicode(true);

CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);

HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);

htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

XMLWorkerHelper.getInstance().getDefaultCssResolver(true);

XMLWorkerHelper.getInstance().parseXHtml(pdfWriter, document, in, null, Charset.forName("UTF-8"),

fontProvider);

// XMLWorkerHelper.getInstance().parseXHtml(pdfWriter, document, in, Charset.forName("UTF-8"),new AsianFontProvider());

document.close();

} catch (Exception e) {

e.printStackTrace();

} finally {

if (fos != null) {

try {

fos.close();

} catch (IOException e) {

e.printStackTrace();

}

}

if (document != null) {

document.close();

}

}

return "success";

}

// 读html模板代码

private static String readString(String filePath) {

File file = new File(filePath);

String result = "";

try {

FileInputStream in = new FileInputStream(file);

// size 为字串的长度 ,这里一次性读完

int size = in.available();

byte[] buffer = new byte[size];

in.read(buffer);

in.close();

result = new String(buffer,"UTF-8");

} catch (IOException e) {

e.printStackTrace();

}

return result;

}

/**

* 替换掉模板中的占位符

* @param html 模板代码

* @param map 替换模板的值

* @return

*/

private String htmlSetValue(String html,Map map){

if(StringUtils.isBlank(html) || MapUtils.isEmpty(map)){

return html;

}

for (String key : map.keySet()) {

html = html.replaceAll("#"+key,MapUtils.getString(map,key,""));

}

return html;

}

字体类:

public class AsianFontProvider extends XMLWorkerFontProvider {

public AsianFontProvider() {

super(null,null);

}

@Override

public Font getFont(final String fontname, String encoding, float size, final int style) {

String fntname = fontname;

if (fntname == null) {

fntname = "宋体";

}

if (size == 0) {

size = 4;

}

return super.getFont(fntname, encoding, size, style);

}

}

HTML模板太大 贴一小段 使用 #key 在替换的时候把所有的占位符替换为自己想要的值

比如 map中的键值对为: #addres,北京市朝阳区 这样在html中要显示地址的地方写 #address即可:

址:#address

高:

style="font-family:'Microsoft YaHei'; font-size:8pt">#heightcm

重:

style="font-family:'Microsoft YaHei'; font-size:8pt">#weightkg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值