前置文件处理
- 将doc文档保存成${} 的样子。
- 另存为xml格式文件
- 重命名ftl文件
- 打开之后格式化数据。
- 更改数据添加默认值 ${name!‘’} 就是在其后添加 !‘’ ,表示默认为空字符串
- list循环数据,在w:tr标签外添加一层 <#list nameList as name> …</#list>
- img 替换base64为${img}, 保存文件。
- 注意要取消文档内表格行之间的间距,可以将<w:tc><w:p> <w:pPr>中的<w:spacing >标签替换成
<w:spacing w:after=“100” w:afterAutospacing=“1” w:line=“0”
w:lineRule=“atLeast” />
填充值 并且导出pdf - 项目中添加freemarker依赖,
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
<!-- docx转pdf-->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-JAXB-Internal</artifactId>
<version>8.2.4</version>
</dependency>
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-export-fo</artifactId>
<version>8.2.4</version>
</dependency>
<!-- https://www.e-iceblue.cn/spiredocforjava/spire-doc-for-java-program-guide-content.html-->
<!-- https://mvnrepository.com/artifact/e-iceblue/spire.doc.free -->
<!-- itextpdf,导出pdf核心架包 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
<!-- itextpdf工具包,用来解析html生成pdf -->
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.11</version>
</dependency>
<!-- flying saucer,支持对CSS高级特性的解析 -->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.5</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-itext5</artifactId>
<version>9.1.5</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>15.8.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/aspose-words-15.8.0-jdk16.jar</systemPath>
</dependency>
<!--文件转换end-->
在项目跟路径下添加lib文件夹,里面放aspose-words-15.8.0-jdk16.jar 包
resource目录下要放 ,这是apose的证书,加完可以去apose的水印。
2. pom中添加 true
不加这个的话打包发版后会找不到项目中的jar包
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope> <!--本地打包包含本地jar包-->
</configuration>
</plugin>
</plugins>
工具类
import com.aspose.words.License;
import com.itextpdf.text.pdf.BaseFont;
import com.petm.common.utils.StringUtils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.docx4j.Docx4J;
import org.docx4j.convert.out.FOSettings;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFont;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.opendope.questions.Response;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* 获取freemarker模板字符串
*/
@Slf4j
@Component
public class FreeMarkUtils {
/**
* 加载license 用于破解 不生成水印
*/
@SneakyThrows
public static void getLicense() {
try (InputStream is = Response.Free.class.getClassLoader().getResourceAsStream("License.xml")) {
License license = new License();
license.setLicense(is);
}
}
static Configuration freemarkerCfg;
// 获设置模板路径
static {
freemarkerCfg =new Configuration();
//freemarker的模板目录
try {
// freemarkerCfg.setClassForTemplateLoading(FreeMarkUtils.class,"/template/ftl");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static String freeMarkerRender(String htmlTmp, Map<String, Object> data) {
Writer out = new StringWriter();
try {
// 获取模板,并设置编码方式
Template template = freemarkerCfg.getTemplate(htmlTmp);
template.setEncoding("UTF-8");
// 合并数据模型与模板
template.process(data, out); //将合并后的数据和模板写入到流中,这里使用的字符流
out.flush();
return out.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
return null;
}
public static void createPdf(String content,OutputStream out) throws IOException, com.lowagie.text.DocumentException {
ITextRenderer render = new ITextRenderer();
ITextFontResolver fontResolver = render.getFontResolver();
Map<String, PhysicalFont> physicalFonts = PhysicalFonts.getPhysicalFonts();
fontResolver.addFont("STSongStd-Light","UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
// 解析html生成pdf
render.setDocumentFromString(content);
//解决图片相对路径的问题
//render.getSharedContext().setBaseURL("");
render.layout();
render.createPDF(out);
render.finishPDF();
}
/**
* 获得图片的Base64编码
*
* @param imgFile
* @return
* @Author Huang Xiaocong 2018年12月15日 下午10:15:10
*/
public static String getImageStr() throws IOException {
FileInputStream inputStream = null;
try {
Base64.Encoder encoder = Base64.getEncoder();
inputStream = new FileInputStream("/Users/wsj/Downloads/半开窗户壁纸.jpeg");
int available = inputStream.available();
byte[] bytes = new byte[available];
inputStream.read(bytes);
String base64Str = encoder.encodeToString(bytes);
return base64Str;
} catch (Exception e) {
e.printStackTrace();
}finally {
inputStream.close();
}
return "fail";
}
}
测试类
@GetMapping("v4")
public void test4() throws Exception {
getLicense();
try{
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
// 本地路径
// resource下路径
configuration.setClassForTemplateLoading(FreeMarkUtils.class,"/template/ftl");
Template template = configuration.getTemplate("k.ftl");
StringWriter swriter = new StringWriter();
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("petNickName", "兜兜");
List<Map<String, String>> mapList = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Map<String, String> map = new HashMap<>();
map.put("name", "阿莫西林");
map.put("sallNum", "10");
map.put("sallUnit", "ml");
map.put("remark", "注射,一次1ml");
mapList.add(map);
}
List<Map<String, String>> checkList = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Map<String, String> map = new HashMap<>();
map.put("itemType", "阿莫西林");
map.put("itemName", "10");
checkList.add(map);
}
List<Map<String, String>> treatList = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Map<String, String> map = new HashMap<>();
map.put("treatName", "阿莫西林");
treatList.add(map);
}
dataMap.put("drugList", mapList);
dataMap.put("checkList", checkList);
dataMap.put("treatList", treatList);
String url = "http://11.7.21.10:9000/dev/半hh.jpeg";
String fileObjectName = url.substring(url.lastIndexOf("dev" + "/")
+ "dev".length());
dataMap.put("img", FreeMarkUtils.getImageStr());
template.process(dataMap,swriter);
//此处的两种方法都可以进行尝试
//当时打成jar包运行后会报FileCorruptedException: The document appears to be corrupted and cannot be loaded错误,改成UTF-8格式就解决了,特此记录
ByteArrayInputStream is = new ByteArrayInputStream(swriter.toString().getBytes(StandardCharsets.UTF_8));
Document doc = new Document(is);
//PDF的路径
doc.save("/Downloads/fff.pdf");
doc.save("/Downloads/ddd.doc");
} catch (Exception e) {
e.printStackTrace();
}
}