摘要:工作中需要将word 模板的合同,替换内容,转为pdf 文件,用于查看与打印,并寄送给客户签字,使用的工具是Apache的poi,在windows中没任何问题, 部署在Ubuntu上的时候, 导出的却是乱七八糟的东西, 起初认为是编码问题,一直纠结,让码农好苦逼, 后面发现不管怎么调编码都没有用,后面怀疑是 字体问题,(就是在转pdf时,需要用到相应的字体来显示原生word中的字体设置效果),后面发现在Ubuntu系统中没有对应的字体,于是将需要的中文字体安装到系统中,就解决了
maven依赖:
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
<version>1.0.4</version>
</dependency>
核心代码:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.MapUtils;
import org.apache.poi.xwpf.converter.pdf.PdfConverter;
import org.apache.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.opensagres.xdocreport.utils.StringUtils;
/**
* @author Rocca
*
*/
public class WordPdfUtils {
protected static final Logger logger = LoggerFactory.getLogger(WordPdfUtils.class);
public static void main(String[] args) throws Exception{
String filepath = "C:/Users/Rocca/Desktop/vork/xxx.docx";
String outpath = "F:/test.pdf";
InputStream source = new FileInputStream(filepath);
OutputStream target = new FileOutputStream(outpath);
Map<String, String> params = new HashMap<String, String>();
PdfOptions options = PdfOptions.create();
wordConverterToPdf(source, target, options, params);
}
/**
* 将word文档, 转换成pdf, 中间替换掉变量
* @param source 源为word文档, 必须为docx文档
* @param target 目标输出
* @param params 需要替换的变量
* @throws Exception
*/
public static void wordConverterToPdf(InputStream source,
OutputStream target, Map<String, String> params) throws Exception {
wordConverterToPdf(source, target, null, params);
}
/**
* 将word文档, 转换成pdf, 中间替换掉变量
* @param source 源为word文档, 必须为docx文档
* @param target 目标输出
* @param params 需要替换的变量
* @param options PdfOptions.create().fontEncoding( "windows-1250" ) 或者其他
* @throws Exception
*/
public static void wordConverterToPdf(InputStream source, OutputStream target,
PdfOptions options,
Map<String, String> params) throws Exception {
XWPFDocument doc = new XWPFDocument(source);
paragraphReplace(doc.getParagraphs(), params);
for (XWPFTable table : doc.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
paragraphReplace(cell.getParagraphs(), params);
}
}
}
PdfConverter.getInstance().convert(doc, target, options);
}
/** 替换段落中内容 */
private static void paragraphReplace(List<XWPFParagraph> paragraphs, Map<String, String> params) {
if (MapUtils.isNotEmpty(params)) {
for (XWPFParagraph p : paragraphs){
for (XWPFRun r : p.getRuns()){
String content = r.getText(r.getTextPosition());
logger.info(content);
if(StringUtils.isNotEmpty(content) && params.containsKey(content)) {
r.setText(params.get(content), 0);
}
}
}
}
}
}
字体安装:
这里就把window上的字体打包,选择中文字体就行,上传到Linux系统, 安装好就成。
window系统中的字体路径: C:\Windows\Fonts 下
Linux系统的字体有多个地方, 我这里放在:/usr/share/fonts 目录下,在其中建立了一个win目录,
用于存放上传的中文字体,再执行命令: fc-cache -fv 将字体刷到字体缓存中。然后重启下应用。