java转word freemaker_Java利用Freemark生成word文档

这是一个关于如何在Java应用程序中利用Freemarker库生成Word文档的示例。控制器类`ClientController`中包含了处理批量下载的方法,通过异步线程`AsynMakeDoc`来生成和压缩多个Word文档。同时,它使用了`DeepOove`的PoiTemplate进行模板渲染,并结合`FreemarkerUtil`处理数据。最后,生成的文档会被上传到OSS存储服务。
摘要由CSDN通过智能技术生成

packagecom.xxxx.modules.api.controller;importcom.alibaba.fastjson.JSONObject;importcom.baomidou.mybatisplus.core.toolkit.IdWorker;importcom.deepoove.poi.XWPFTemplate;importcom.deepoove.poi.config.Configure;importcom.xxxx.common.utils.FreemarkerUtil;importcom.xxxx.common.utils.PoiUtil;importcom.xxxx.common.utils.ZipUtil;importcom.xxxx.modules.constant.ApiConsts;importcom.xxxx.modules.framework.PendingJobPool;importcom.xxxx.modules.framework.vo.TaskResult;importcom.xxxx.modules.framework.vo.TaskResultType;importcom.xxxx.modules.heath.dto.TCPatientsDTO;importcom.xxxx.modules.heath.dto.TCPhsUserDTO;importcom.xxxx.modules.heath.dto.TCTransportLogDTO;importcom.xxxx.modules.heath.entity.TCTransportLogEntity;import com.xxxx.modules.heath.service.*;importcom.xxxx.modules.jt.service.SingleTablePolicy;importcom.xxxx.modules.jt.service.WordService;importcom.xxxx.modules.oss.cloud.OSSFactory;importfreemarker.template.Template;importio.renren.common.annotation.LogOperation;importio.renren.common.constant.Constant;importio.renren.common.utils.ConvertUtils;importio.renren.common.utils.Result;importio.swagger.annotations.Api;importio.swagger.annotations.ApiOperation;importlombok.extern.slf4j.Slf4j;importorg.apache.commons.collections.MapUtils;importorg.apache.commons.lang3.StringUtils;importorg.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;import java.io.*;importjava.nio.charset.StandardCharsets;import java.util.*;import java.util.concurrent.*;importjava.util.stream.Collectors;importjava.util.zip.Adler32;importjava.util.zip.CheckedOutputStream;importjava.util.zip.ZipOutputStream;

@Slf4jpublic classClientController {//缓存批量下载的jobName

public static Map batchJobNameCache = new HashMap<>();//取得机器的cpu数量

public static final int THREAD_COUNTS =Runtime.getRuntime().availableProcessors();public static ExecutorService docMakePool = Executors.newFixedThreadPool(THREAD_COUNTS*2);@GetMapping("xxxx")

@ApiOperation("批量下载")

@LogOperation("批量下载")

@ResponseBodypublic Result batchDownloadPlanscode(@RequestParam Map params,HttpServletRequest request) throwsException {//参数判断

//判断任务是否已经存在(防重复)

String jobName = "xxxx";

String jobNameExist= MapUtils.getString(batchJobNameCache, jobName, "");if(StringUtils.isNotEmpty(jobNameExist)){

log.info(tipStr+ "下载正在处理中,请耐心等待~");return new Result().error(201, tipStr + "下载正在处理中,请耐心等待~");

}//1、数据库取模板路径,获得模板实例

String url =xxxxService.getTemplateUrl(planCode, downType);if(StringUtils.isEmpty(url)){

log.info("模板url为空");return new Result().error(202, "请先指定模板~");

}//本次任务显示的中文名称(作为客户端显示)——根据实际需求,看是否需要,可以是客户端传参

String downName = "xxxx";//2、这个根据项目实际需求

List list =xxxxxService.getByPlansCode(planCode);if(list.isEmpty()){

log.info("没有可下载的数据");return new Result().error(201, "暂无该场次报告数据!");

}//本批次任务记录的主键

Long id =IdWorker.getId();

batchJobNameCache.put(jobName,0);//3、另起一个线程处理下载任务(重要)

new Thread(newAsynMakeDoc(id, jobName, list, url)).start();//4、记录下载痕迹

TCTransportLogDTO dto = newTCTransportLogDTO();

dto.setId(id);

dto.setUserName(phsUser.getUserName());//当前用户

dto.setBusinessType(ApiConsts.TRANSMISSION_UPLOAD);//上传(生成报告-打zip包-上传oss)

dto.setStatus(1);//有效

dto.setJobName(jobName);//批次任务唯一标识

dto.setResultName(downName);//批次任务中文名称,作为下载记录的显示在客户端

dto.setJobType(0);//0-批次,1-子任务

dto.setCreateDate(newDate());

tcTransportLogService.insert(ConvertUtils.sourceToTarget(dto, TCTransportLogEntity.class));return new Result().success(200, "添加下载新任务成功~", jobName + "," +id);

}/*** 异步处理word生成*/

class AsynMakeDoc implementsRunnable{private Long id;//主键

private String jobName;//场次号_档案_用户

private Listlist;privateString templateUrl;public AsynMakeDoc(Long id, String jobName, Listlist, String templateUrl) {this.jobName =jobName;this.list =list;this.downType =downType;this.templateUrl =templateUrl;this.id =id;

}

@Overridepublic voidrun() {

Object template;//取oss模板的后缀

String templateType =wordService.getType(templateUrl);if(ApiConsts.TEMPLATE_TYPE_XML.equals(templateType)){

templateType=ApiConsts.TEMPLATE_TYPE_XML;

template=FreemarkerUtil.getTemplate(templateUrl);

}else{

templateType=ApiConsts.TEMPLATE_TYPE_POI;//多个自定义渲染策略

Configure configures =Configure.createDefault();

configures.customPolicy("urines", new SingleTablePolicy(1, 5));

configures.customPolicy("bloods", new SingleTablePolicy(1, 5));

configures.customPolicy("examines", new SingleTablePolicy(1, 5));

template=PoiUtil.getTemplate(templateUrl, configures);

}String fileName= "_报告.doc";

String zipName= "_报告.zip";String plansCode= list.get(0).getPlansCode();//报告、压缩包临时路径

String outTempPath = "";

String zipPath= "";//更新批次下载记录状态

TCTransportLogEntity dto = newTCTransportLogEntity();

dto.setId(id);

dto.setJobType(1);//不管成功失败,批次任务变更为子任务

dto.setBusinessType(ApiConsts.TRANSMISSION_DOWNLOAD);//变更为下载

File zipFile= null;

ZipOutputStream zos= null;//生成目标文件对象的输出流

OutputStream outputStream = null;try{//临时压缩包目录:本地磁盘/jobName.zip(jobName需保证多用户并发时候不会相互干扰)

outTempPath =getTempPath();

zipPath= outTempPath + jobName + ".zip";

zipFile= newFile(zipPath);

log.info("temporary zip :" +zipPath);

outputStream= newFileOutputStream(zipPath);

CheckedOutputStream cos= new CheckedOutputStream(outputStream, newAdler32());//生成ZipOutputStream,用于写入要压缩的文件

zos = newZipOutputStream(cos);//1、往线程池添加任务

log.info(" start generating words...");

CompletionService docCompletionService = new ExecutorCompletionService(docMakePool);for (int i = 0; i < list.size(); i++) {

docCompletionService.submit(new DocMakeTask(list.get(i), fileName, template, outTempPath +jobName, templateType));

}//计算已打成完成数量

int zipCount = 0;//2、从线程池取执行结果进行压缩

for (int j = 0; j < list.size(); j++) {//阻塞取结果

Future future =docCompletionService.take();//判断要压缩的源文件是否存在

String path =future.get();if (!StringUtils.isEmpty(path)) {

File sourceFile= newFile(path);if (!sourceFile.exists()) {throw new RuntimeException("[" + sourceFile + "] is not exists ...");

}

ZipUtil.compressFile(sourceFile, zos, sourceFile.getName(),true);if(sourceFile.exists()) {

sourceFile.delete();

}

zipCount++;//通过应用缓存更新处理进度

log.info("压缩进度:" + zipCount + "/" + list.size() + " : " + zipCount*100/list.size());

batchJobNameCache.put(jobName, zipCount*100/list.size());

}

}//关闭压缩流(不然上传的文件是不完整的)

zos.finish();

zos.close();

outputStream.close();long s1 =System.currentTimeMillis();

log.info(jobName+ ".zip completed,耗时:" + (s1 -start));//删除临时文件夹

File docTempDir = new File(outTempPath +jobName);if(docTempDir.exists()){

docTempDir.delete();

log.info(" temporary folder " + jobName + " has been deleted ");

}

log.info(" ready to upload ");//3、压缩包上传oss,路径自定义:场次号/场次号_healthy.zip

FileInputStream inputStream = null;

String ossPathName= downType + "/" + plansCode + "/"+ System.currentTimeMillis() + "/" + plansCode +zipName;

String ossPath= "";try{

inputStream= newFileInputStream(zipPath);

ossPath=OSSFactory.build().upload(inputStream, ossPathName);

batchJobNameCache.put(jobName+ "_ossPath", ossPath);

log.info("upload complete , ossPath:" +ossPath);

dto.setResultReturn(ossPath);

dto.setResultType(String.valueOf(TaskResultType.Success));

}catch(Exception e){

dto.setResultType(String.valueOf(TaskResultType.Failure));

batchJobNameCache.put(jobName+ "_ossPath", String.valueOf(TaskResultType.Failure));//batchJobNameCache.remove(jobName);

dto.setResultReason("上传压缩包失败");

log.info(" upload zip failure ");

}finally{if(inputStream != null){

inputStream.close();

}

}

}catch(Exception e) {

dto.setResultReason("打包失败");

batchJobNameCache.put(jobName+ "_ossPath", String.valueOf(TaskResultType.Failure));//batchJobNameCache.remove(jobName);

dto.setResultType(String.valueOf(TaskResultType.Failure));

log.info(" zip failure ");

}finally{//删除压缩包

if(zipFile.exists()) {

zipFile.delete();

log.info(jobName+ ".zip has been deleted ! ");

}//更新批次任务为子任务状态(0->1)

tcTransportLogService.updateById(dto);

}

}

}/*** 生成wor并返回相应path*/

class DocMakeTask implements Callable{privateTCPatientsDTO tcPatientsDTO;privateObject template;privateString fileName;private String outPath; //生成报告的临时根目录

privateString templateType;publicDocMakeTask(TCPatientsDTO tcPatientsDTO, String fileName, Object template, String outPath, String templateType) {this.tcPatientsDTO =tcPatientsDTO;this.fileName =fileName;this.template =template;this.outPath =outPath;this.templateType =templateType;

}

@Overridepublic String call() throwsException {//生成的报告的临时目录

String docTempPath = "";//取模板填充数据

Map dataMap = "";docTempPath= outPath + File.separator + "xxx_xxx" +fileName;//生成报告

if(ApiConsts.TEMPLATE_TYPE_XML.equals(templateType)){

FreemarkerUtil.createWordByTemplate((Template) template, docTempPath, dataMap);

}else{

PoiUtil.writeToFileByTemplate((XWPFTemplate) template, docTempPath, dataMap);

}

log.info("word :" +docTempPath);returndocTempPath;

}

}

@GetMapping("archives")

@ApiOperation("单份报告下载")

@LogOperation("单份报告下载")

@ResponseBodypublic Result archives(@RequestParam Map params, HttpServletRequest request) throwsException {//参数判空处理等都略过。。。//根据业务类型取取模板实例(通过oss链接取模板)

String url =wordService.getTemplateUrl(plansCode, downType);if(StringUtils.isEmpty(url)){

log.info("模板链接为空");return new Result().error(202, "请先指定报告模板");

}//取oss模板的后缀(项目支持POI和xml)

String templateType =wordService.getType(url);if(ApiConsts.TEMPLATE_TYPE_XML.equals(templateType)){ //"xml"

templateType=ApiConsts.TEMPLATE_TYPE_XML;

}else{ //"poi"

templateType=ApiConsts.TEMPLATE_TYPE_POI;

}//2、取业务类型对应数据

Map dataMap = new HashMap<>();if(ApiConsts.RESIDENT_HEALTHY.equals(downType)){ //健康档案

dataMap =wordService.getDataMapPoi(plansCode, sn, ApiConsts.RESIDENT_HEALTHY, templateType);

}else if(ApiConsts.RESIDENT_REPORT.equals(downType)){ //体检报告

dataMap =wordService.getDataMapPoi(plansCode, sn, ApiConsts.RESIDENT_REPORT, templateType);

}

String name= MapUtils.getString(dataMap, "name");//oos名称:{downType}/{planscoe}/时间戳/{sn}_{name}_xxx.doc

String ossPathName = downType + "/" + plansCode + "/" + System.currentTimeMillis() + "/" + sn + "_" + name + "_" +fileName;//记录下载痕迹

TCTransportLogDTO dto = null;

String userName=phsUser.getUserName();//上传oss返回的链接

String ossPath = "";try{if(ApiConsts.TEMPLATE_TYPE_POI.equals(templateType)){//临时目录

String outTempPath = wordService.getTempPath() + File.separator + sn + "_" + name +fileName;//多个自定义渲染策略

Configure configures =Configure.createDefault();

configures.customPolicy("urines", new SingleTablePolicy(1, 5));

configures.customPolicy("bloods", new SingleTablePolicy(1, 5));

configures.customPolicy("examines", new SingleTablePolicy(1, 5));

XWPFTemplate template=PoiUtil.getTemplate(url, configures);

template.render(dataMap);

template.writeToFile(outTempPath);

template.close();

ossPath= OSSFactory.build().upload(newFileInputStream(outTempPath), ossPathName);//删除本地临时文件

ZipUtil.delFile(newFile(outTempPath));

}else{

StringWriter out= newStringWriter();

Template template=FreemarkerUtil.getTemplate(url);

template.process(dataMap, out);

ossPath=OSSFactory.build().upload(out.toString().getBytes(StandardCharsets.UTF_8), ossPathName);

}

log.info(sn+ "_" + name + fileName + "生成! doc link:" +ossPath);

dto= newTCTransportLogDTO();

dto.setUserName(userName);

dto.setBusinessType(ApiConsts.TRANSMISSION_DOWNLOAD);//下载

dto.setStatus(1);//有效

dto.setJobType(1);//子任务类型

dto.setResultType(String.valueOf(TaskResultType.Success));//下载成功

dto.setResultReturn(ossPath);//下载存储路径

dto.setResultName(sn + "_" + name + fileName);//下载后文件名称

dto.setCreateDate(newDate());return new Result().success(200, tipStr + "下载完成", ossPath);

}catch(Exception e){

dto.setResultReturn("");//下载存储路径

dto.setResultType(String.valueOf(TaskResultType.Failure));

dto.setResultReason("下载失败");

log.info(sn+ "_" + name + fileName + " 下载失败!");return new Result().success(201, tipStr + "下载失败", "");

}finally{

tcTransportLogService.insert(ConvertUtils.sourceToTarget(dto, TCTransportLogEntity.class));

}

}

@GetMapping("progressList")

@ApiOperation("下载完成记录列表")

@LogOperation("下载完成记录列表")public Result getProgressList(@RequestParam Mapparams, HttpServletRequest request){//取当前用户下的所有子任务(businessType:==1表示上传完毕(待下载),==2表示已下载)

List list =DB.getxxxx(xxx);if(list.isEmpty()){return new Result().success(201, "暂无下载记录~", list);

}return new Result().success(200, "获取下载记录成功", list);

}

@GetMapping("getInTransit")

@ApiOperation("获取打包中列表")

@LogOperation("获取打包中列表")public Result getInTransit(@RequestParam Mapparams, HttpServletRequest request){Integer businessType= MapUtils.getInteger(params, "businessType", ApiConsts.TRANSMISSION_UPLOAD);//获取所有批量任务

List list = tcTransportLogService.getInTransit(phsUser.getUserName(), 0, businessType);if(list.isEmpty()){return new Result().success(201, "暂无下载中任务~", list);

}//实际正在进行的列表

List returnList = new ArrayList<>();//异常任务+已完成任务

List completeList = new ArrayList<>();//下载任务异常列表

List updateList = new ArrayList<>();for(TCTransportLogDTO dto : list){

String jobName=dto.getJobName();//1、缓存中不存在(已完成或者任务没有正常结束两种)

String existJobName = MapUtils.getString(batchJobNameCache, jobName, "");if(StringUtils.isEmpty(existJobName)){if(StringUtils.isEmpty(dto.getResultType())){

dto.setResultType(String.valueOf(TaskResultType.Exception));

dto.setResultReason("任务没有正常结束");

dto.setJobType(1);//任务改为子任务

updateList.add(ConvertUtils.sourceToTarget(dto, TCTransportLogEntity.class));

}

completeList.add(ConvertUtils.sourceToTarget(dto, TCTransportLogEntity.class));continue;

}try{//2、正在进行的工作

int percent =Integer.parseInt(existJobName);

dto.setPercertage(percent);

}catch(Exception e){

e.printStackTrace();

}

returnList.add(dto);

}//处理打包异常

if(!updateList.isEmpty()){

log.info("任务没有正常结束:" +updateList.size());//2、更新数据库状态为异常

tcTransportLogService.updateBatchById(updateList);//检查已完成的列表,删除临时文件

handlerAbnormalTask(completeList);

}if(returnList.isEmpty()){return new Result().success(201, "暂无下载中任务~", returnList);

}return new Result().success(200, "获取下载任务成功", returnList);

}/*** 处理批量下载[下载失败/打包异常]任务

*@paramcompleteList 已完成的列表*/

private void handlerAbnormalTask(ListcompleteList) {

String outTempPath=wordService.getTempPath();for(TCTransportLogEntity entry : completeList){

File zipFile= new File(outTempPath + File.separator + entry.getJobName() + ".zip");

ZipUtil.delFile(zipFile);

File temFileDir= new File(outTempPath + File.separator +entry.getJobName());

ZipUtil.delFile(temFileDir);

}

log.info("delete complete or exception task...");

}/*** 以服务器的最后一个磁盘作为临时目录(返回字符串带文件分隔符)

*@return

*/

privateString getTempPath() {//本地磁盘的根路径

File[] paths =File.listRoots();return paths[paths.length-1].getAbsolutePath();

}

@PostMapping("queryProcess")

@ApiOperation("查询打包进度")

@LogOperation("查询打包进度")public Result queryProcess(@RequestBody Mapparams){

String taskList= MapUtils.getString(params, "jobNames", "");if(StringUtils.isEmpty(taskList)){return new Result().success(201, "下载完成", null);

}

List jobNameList = JSONObject.parseArray(taskList, TCTransportLogDTO.class);

List returnList = new ArrayList<>();//遍历列表,分开已经完成并过期的工作(

for(TCTransportLogDTO dto : jobNameList){

String jobName=dto.getJobName();//1)、缓存中不存在的

String existJobName = MapUtils.getString(batchJobNameCache, jobName, "");if(StringUtils.isEmpty(existJobName)){continue;

}//2)、刷新进度条显示

if(dto.getPercertage() == 100 ){ //打包完成,下载中

dto.setRemark("下载中...");

}else{ //进度 < 100,刷新打包中任务进度

int percent = MapUtils.getIntValue(batchJobNameCache, jobName, 0);

dto.setPercertage(percent);

dto.setRemark("打包中...");

}

returnList.add(dto);

}if(returnList.isEmpty()){return new Result().success(201, "下载完成", returnList);

}return new Result().success(200, "刷新打包进度条", returnList);

}

@GetMapping("monitorPackage")

@ApiOperation("监听打包")

@LogOperation("监听打包")public Result monitorPackage(@RequestParam Mapparams, HttpServletResponse response){

String jobName= MapUtils.getString(params, "jobName", "");if(StringUtils.isEmpty(jobName)){

log.info("[ monitorPackage ] jobName parameter is missing");return new Result().error(202, "jobName parameter is missing");

}

String jobNameExist= MapUtils.getString(batchJobNameCache, jobName, "");if(StringUtils.isEmpty(jobNameExist)){

log.info("[ monitorPackage ] [" + jobName + "] is not found");return new Result().error(202, "[" + jobName + "] is not found");

}//进度

int percentage =MapUtils.getIntValue(batchJobNameCache, jobName);//打包完成后,判断oss链接

String ossPath = MapUtils.getString(batchJobNameCache, jobName + "_ossPath");if(StringUtils.isEmpty(ossPath)){

log.info("zip being packaged");return new Result().success(201, "zip being packaged", percentage);

}else{//2、从缓存中剔除

batchJobNameCache.remove(jobName);

batchJobNameCache.remove(jobName+ "_ossPath");

log.info(" remove from batchJobNameCache cache ");if(String.valueOf(TaskResultType.Failure).equals(ossPath)){//打包失败/上传失败==下载失败

log.info(percentage==100 ? "上传失败" : "打包失败");return new Result().success(202, percentage==100 ? "上传失败" : "打包失败", ossPath);

}//下载成功

log.info("package is complete, ready to download ");return new Result().success(200, "package is complete, ready to download ", ossPath);

}

}

@GetMapping("queryDetail")

@ApiOperation("查询详情")

@LogOperation("查询详情")public String queryDetail(@RequestParam("jobName") String jobName){

List> taskDetail =pendingJobPool.getTaskDetail(jobName);if(!taskDetail.isEmpty()){returntaskDetail.toString();

}return null;

}

@GetMapping("clearMark")

@ApiOperation("清除下载记录")

@LogOperation("清除下载记录")public Result clearMark(@RequestParam Mapparams, HttpServletRequest request){

String clearIds= MapUtils.getString(params, "clearIds", "");if(StringUtils.isEmpty(clearIds)) {

log.info("传输完成记录主键为空");return new Result().error(201, "丢失需要清除的记录主键信息");

}

List listIds = Arrays.asList(clearIds.split(",")).stream().map(s ->Long.parseLong(s.trim())).collect(Collectors.toList());int row =tcTransportLogService.clearByIds(listIds);if(row ==listIds.size()){

log.info("清除传输记录成功");return new Result().success(200, "清除成功", row);

}

log.info("清除传输记录失败");return new Result().success(202, "清除失败", row);

}

}

可以使用itextpdf和freemarker来实现Java中的HTMLPDF功能。首先,确保你的项目已经引入了相关的依赖,包括spring-boot-starter-freemarker、itextpdf、xmlworker和itext-asian。 接下来,你可以创建一个HtmlConvertPdfHelper类来实现HTMLPDF的功能。在这个类中,你可以使用freemarker来生成HTML内容,并使用itextpdf将HTML内容换为PDF文件。可以参考以下代码: ```java import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.pdf.PdfWriter; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import java.io.*; import java.util.Map; public class HtmlConvertPdfHelper { public byte[] htmlConvertPDF(String templateName, Map<String, String> data) throws IOException, TemplateException, DocumentException { // 加载freemarker配置 Configuration configuration = new Configuration(Configuration.VERSION_2_3_23); configuration.setClassForTemplateLoading(getClass(), "/"); // 获取freemarker模板 Template template = configuration.getTemplate(templateName); // 使用StringWriter来保存生成的HTML内容 StringWriter writer = new StringWriter(); template.process(data, writer); // 使用itextpdf将HTML内容换为PDF Document document = new Document(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PdfWriter.getInstance(document, baos); document.open(); InputStream is = new ByteArrayInputStream(writer.toString().getBytes()); com.itextpdf.tool.xml.XMLWorkerHelper.getInstance().parseXHtml(PdfWriter.getInstance(document, baos), document, is); document.close(); // 返回换后的PDF文件内容 return baos.toByteArray(); } } ``` 接下来,你可以在测试类中调用HtmlConvertPdfHelper类来完成HTMLPDF的操作。首先,创建一个Map对象来存储模板中的变量值,然后调用htmlConvertPDF方法将HTML内容换为PDF,并将换后的PDF内容保存到文件中。 ```java import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class Test { private static final Logger LOGGER = LoggerFactory.getLogger(Test.class); @Test public void aaa() throws IOException, TemplateException, com.itextpdf.text.DocumentException { Map<String, String> data = new HashMap<>(); data.put("name", "鹤顶红"); data.put("type", "毒药"); byte[] bytes = new HtmlConvertPdfHelper().htmlConvertPDF("demo.ftl", data); OutputStream os = new FileOutputStream("G:/text.pdf"); os.write(bytes, 0, bytes.length); os.flush(); os.close(); LOGGER.info("换完成"); } } ``` 通过以上代码,你可以实现Java中的HTMLPDF功能。你需要按照你的实际情况进行适当的修改,如模板名称、变量值等。请确保模板文件存在,并且与HtmlConvertPdfHelper类处于相同的目录下。 希望这个回答能帮到你。如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值