word转pdf加水印以及替换内容

pom文件

<!--依赖springboot-start中dependencyManagement的版本-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>${freemarker.version}</version>
        </dependency>

        <!--itextpdf-->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.3.4</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-pdfa</artifactId>
            <version>5.5.13.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>1.2.1</version>
        </dependency>
        <!--没有该包的话,会有中文显示问题-->
        <dependency>
            <groupId>com.lowagie</groupId>
            <artifactId>itext</artifactId>
            <version>2.1.7</version>
        </dependency>

        <!--xdocreport-->
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
            <version>1.0.6</version>
        </dependency>
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>org.apache.poi.xwpf.converter.xhtml</artifactId>
            <version>1.0.6</version>
        </dependency>

java文件



import com.hanxiaozhang.constant.ContractConstant;
import com.hanxiaozhang.watermarkutil.PDFWatermarkPrint;
import com.hanxiaozhang.watermarkutil.WatermarkPrint;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.HashMap;
import java.util.Map;


/**
 * 功能描述: <br>
 * 〈word转pdf, pdf转word工具类测试〉
 *
 */
@Slf4j
public class WordUtilTest {


    public static void main(String[] args) throws Exception {

        String docx = "D:\\test\\test.docx";
        WordUtil.getInstance().execute(docx,"test",initData(),"test11");
    }


    /**
     * 初始化docx文件中的变量数据
     * @return
     */
    public static Map initData() {
        Map<String, String> data = new HashMap<>(4);
        data.put("test", "tese");
        return data;
    }
}
@Slf4j
public class WordUtil {

    /**
     * 代表应用程序和URL之间的通信链接
     */
    HttpURLConnection httpURLConnection = null;

    /**
     * 生成pdf路径名
     */
    private String pdfName;

    /**
     * 添加水印的pdf路径名
     */
    private String waterPdfName;

    /**
     * 文件上传到fast的地址
     */
    private String fileUrl;

    private File pdfFile;

    private File waterPdfFile;

    private static class Holder{
        private final static WordUtil INSTANCE = new WordUtil();
    }

    private WordUtil() {
    }

    public static WordUtil getInstance() {
        return Holder.INSTANCE;
    }


    /**
     * 执行生成PDF文件
     */
    public String execute(String fastUrl, String waterMark, Map<String, String> initPdfData, String fileName) {
        this.fileUrl=null;
        this.pdfName = CommonUtil.getDir() + fileName + "-" + DateUtil.format2() + ".pdf";
        log.info("WordUtil--execute-pdfName: {}",pdfName);
        this.waterPdfName = CommonUtil.getDir() + fileName + "-" + DateUtil.format2() + "-1.pdf";
        log.info("WordUtil--execute-waterPdfName: {}",waterPdfName);
        this.pdfFile = new File(pdfName);
        this.waterPdfFile = new File(waterPdfName);
        InputStream is = null;
        try {

            is = getInputStreamByPath(fastUrl);

            // word 转 pdf
            WordUtil.wordToPDF(is, initPdfData, pdfFile, ContractConstant.DOCX);

            watermark(waterMark);

            FileUtil.uploadFile(fileToByte(waterPdfFile), CommonUtil.getDir(), fileName +".pdf");

        } catch (Exception e) {
            log.error("wordToPDF『"+pdfName+"』", e);
        } finally {
            try {
                if (is != null) {
                    is.close();
                }

            } catch (Exception e) {
                log.error("关闭流异常", e);
            }
        }
        log.info("返回生成pdf--execute-fileUrl{}",fileUrl);
        return fileUrl;
    }


    /**
     * word转pdf
     *
     * @param srcInput  doc输入流
     * @param data      需要替换的doc文档变量数据
     * @param targetPdf pdf文件
     * @param fileType  doc或者docx
     * @throws Exception
     */
    public static void wordToPDF(InputStream srcInput, Map<String, String> data, File targetPdf, String fileType) throws Exception {
        if (fileType.endsWith(ContractConstant.DOCX)) {
            byte[] pdfData = bindDocxDataAndToPdf(srcInput, data);
            FileUtils.writeByteArrayToFile(targetPdf, pdfData);
        } else if (fileType.endsWith(ContractConstant.DOC)) {
            byte[] pdfData = bindDocDataAndToPdf(srcInput, data);
            FileUtils.writeByteArrayToFile(targetPdf, pdfData);
        } else {
            throw new RuntimeException("文件格式不正确");
        }
    }


    /**
     * 替换docx文件内容,并转换成PDF
     *
     * @param input docx文件流
     * @param data  替换内容
     * @return pdf文件流
     * @throws Exception
     */
    private static byte[] bindDocxDataAndToPdf(InputStream input, Map<String, String> data) throws Exception {
        byte[] replacedContent = replaceDocxContent(input, data);
        byte[] pdfData = docxToPdf(new ByteArrayInputStream(replacedContent));
        return pdfData;
    }


    /**
     * 替换doc文件内容,并转换成PDF
     *
     * @param input docx文件流
     * @param data  替换内容
     * @return pdf文件流
     * @throws Exception
     */
    private static byte[] bindDocDataAndToPdf(InputStream input, Map<String, String> data) throws Exception {
        byte[] pdfData = new byte[0];
        return pdfData;
    }


    /**
     * docx转成pdf
     *
     * @param docxStream docx文件流
     * @return 返回pdf数据
     * @throws Exception
     */
    private static byte[] docxToPdf(InputStream docxStream) throws Exception {
        ByteArrayOutputStream targetStream = null;
        XWPFDocument doc = null;
        try {
            doc = new XWPFDocument(docxStream);
            PdfOptions options = PdfOptions.create();
            // 中文字体处理
            options.fontProvider(new IFontProvider() {
                @Override
                public Font getFont(String familyName, String encoding, float size, int style, Color color) {
                    try {
                        BaseFont bfChinese = createFont();
                        Font fontChinese = new Font(bfChinese, size, style, color);
                        if (familyName != null) {
                            fontChinese.setFamily(familyName);
                        }
                        return fontChinese;
                    } catch (Exception e) {
                        e.printStackTrace();
                        return null;
                    }
                }

            });

            targetStream = new ByteArrayOutputStream();
            PdfConverter.getInstance().convert(doc, targetStream, options);
            return targetStream.toByteArray();
        } catch (IOException e) {
            throw new Exception(e);
        } finally {
            IOUtils.closeQuietly(targetStream);
        }
    }


    /**
     * doc转成pdf
     *
     * @param docStream doc文件流
     * @return 返回pdf数据
     * @throws Exception
     */
    private static byte[] docToPdf(InputStream docStream) {
        ByteArrayOutputStream targetStream = new ByteArrayOutputStream();
        // todo 待完善doc转成pdf
        return targetStream.toByteArray();
    }


    /**
     * 替换docx内容
     *
     * @param in  docx输入流
     * @param map 替换键值对
     * @return 返回替换后的文件流
     * @throws Exception
     */
    private static byte[] replaceDocxContent(InputStream in, Map<String, String> map) throws Exception {
        // 读取word模板
        XWPFDocument hdt = null;
        ByteArrayOutputStream out = null;
        try {
            hdt = new XWPFDocument(in);
            // 替换段落内容
            List<XWPFParagraph> paragraphs = hdt.getParagraphs();
            if (map != null && !map.isEmpty()) {
                replaceParagraphsContent(paragraphs, map);
            }

            // 替换表格内容
            List<XWPFTable> tables = hdt.getTables();
            // 读取表格
            for (XWPFTable table : tables) {
                int rcount = table.getNumberOfRows();
                // 遍历表格中的行
                for (int i = 0; i < rcount; i++) {
                    XWPFTableRow row = table.getRow(i);
                    // 遍历行中的单元格
                    List<XWPFTableCell> cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        List<XWPFParagraph> cellParagraphs = cell.getParagraphs();
                        if (map != null && !map.isEmpty()) {
                            replaceParagraphsContent(cellParagraphs, map);
                        }
                    }
                }
            }

            out = new ByteArrayOutputStream();
            hdt.write(out);
            return out.toByteArray();
        } catch (IOException e) {
            throw new Exception(e.getMessage());
        } finally {
            IOUtils.closeQuietly(out);
        }
    }


    /**
     * 替换段落内容
     *
     * @param paragraphs
     * @param map
     */
    private static void replaceParagraphsContent(List<XWPFParagraph> paragraphs, Map<String, String> map) {
        for (XWPFParagraph paragraph : paragraphs) {
            List<XWPFRun> runs = paragraph.getRuns();
            for (XWPFRun run : runs) {
                String text = run.getText(0);
                if (text != null) {
                    boolean isSetText = false;
                    for (Map.Entry<String, String> entry : map.entrySet()) {
                        String key = entry.getKey();
                        // 在配置文件中有这个关键字对应的键
                        if (text.indexOf(key) != -1) {
                            String value = entry.getValue();
                            if (value == null) {
                                throw new RuntimeException(key + "对应的值不能为null");
                            }
                            // 文本替换
                            text = text.replace(key, value);
                            isSetText = true;
                        }
                    }
                    if (isSetText) {
                        run.setText(text, 0);
                    }
                }
            }
        }
    }


    /**
     * 创建字体
     *
     * @return
     */
    private static BaseFont createFont() {
        //仿宋体
        String font_cn = getChineseFont();
        BaseFont chinese = null;
        try {
            chinese = BaseFont.createFont(font_cn, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return chinese;
    }


    /**
     * 获取中文字体位置
     *
     * @return
     */
    private static String getChineseFont() {
        // 仿宋体
        String font = "C:/windows/fonts/simfang.ttf";
        // 判断系统类型,加载字体文件
        java.util.Properties prop = System.getProperties();
        String osName = prop.getProperty("os.name").toLowerCase();
        if (osName.indexOf("linux") > -1) {
            font = "/usr/share/fonts/simsun/simfang.ttf";
        }else if(osName.indexOf("mac os x") > -1){
            font="/Users/Downloads/simfang.ttf";
        }
        if (!new File(font).exists()) {
            throw new RuntimeException("字体文件不存在,影响导出pdf中文显示!" + font);
        }
        return font;
    }


    /**
     * 将文件转换成byte数组
     *
     * @param tradeFile
     * @return
     */
    public static byte[] fileToByte(File tradeFile) {
        byte[] buffer = null;
        try {
            FileInputStream fis = new FileInputStream(tradeFile);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }


    /**
     * 添加水印
     *
     * @param waterMark
     */
    private void watermark(String waterMark) {
        WatermarkPrint watermarkPrint = new PDFWatermarkPrint();
        try {
            watermarkPrint.print(pdfFile, new BufferedOutputStream(new FileOutputStream(waterPdfFile)),waterMark, DateUtil.format1());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传到fast
     */
    private void uploadFast() {

        // 上传到文件服务器
        String remoteServerPath = "https://www.xxxx.com/";

        String remoteFilePath = null;

        try {
//            remoteFilePath = FastDfsUtil.upload(fileToByte(waterPdfFile), "pdf");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (StringUtil.isBlank(remoteFilePath)) {
            throw new RuntimeException("文件上传失败,请重新上传!");
        }

        String fileUrl = "";
        // 保存到数据库
        if (remoteServerPath.endsWith("/")) {
            fileUrl = remoteServerPath + remoteFilePath;
        } else {
            fileUrl = remoteServerPath + "/" + remoteFilePath;
        }

        this.fileUrl = fileUrl;
    }


    /**
     * 获取输入流通过Url
     *
     * @param fileUrl
     * @return
     */
    private InputStream getInputStreamByUrl(String fileUrl) {
        InputStream is = null;
        for (int i = 0; i < 3; i++) {
            try {
                URL url = new URL(fileUrl);
                httpURLConnection = (HttpURLConnection) url.openConnection();
                httpURLConnection.setDoInput(true);
                httpURLConnection.setRequestMethod("GET");
                httpURLConnection.setConnectTimeout(30000);
                is = httpURLConnection.getInputStream();
                break;
            } catch(Exception e) {
                log.error("打开文件链接异常, 第【{}】次", i+1 , e);
            }
        }

        return is;
    }

    /**
     * 获取输入流通过path
     *
     * @param path
     * @return
     */
    private InputStream getInputStreamByPath(String path){
        InputStream is = null;
        try {
            is = new FileInputStream(path);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return is;
    }





}
@Slf4j
public class FreemarkerUtil {


	public static Configuration CONFIG;

	public static String renderTemplate(String s, Map<String, Object> data) throws IOException, TemplateException {
		Template t = new Template(null, new StringReader(s), CONFIG);
		// 执行插值,并输出到指定的输出流中
		StringWriter w = new StringWriter();
		t.getConfiguration();
		try {
			t.process(data, w);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("填充模板内容出现异常,模板:"+s);
			log.debug("noticeTime",data.get("noticeTime"));
		}

		return w.getBuffer().toString();
	}

	public static String renderFileTemplate(String file, Map<String, Object> data) throws IOException,
		TemplateException {
		Configuration cfg = CONFIG;
		cfg.setDefaultEncoding("UTF-8");
		// 取得模板文件
		Template t = cfg.getTemplate(file);
		// 执行插值,并输出到指定的输出流中
		StringWriter w = new StringWriter();
		t.getConfiguration();
		t.process(data, w);
		return w.getBuffer().toString();
	}

}
public class PdfHelper {

	private Document document;

	private BaseFont bfChinese;

	/**
	 * 字体
	 */
	@SuppressWarnings("unused")
	private Font font;

	public PdfHelper(String path) {
		document = new Document();
		try {
			// 建立一个PdfWriter对象
			PdfWriter.getInstance(document, new FileOutputStream(path));
			document.open();
			// 设置中文字体
			bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
			// 设置字体大小
			font = new Font(bfChinese, 10, Font.NORMAL);
		} catch (DocumentException de) {

		} catch (IOException ioe) {

		}
	}

	public static PdfHelper instance(String path) {
		return new PdfHelper(path);
	}

	public void exportPdf() {
		document.close();
	}

	public void addHtmlList(List<Element> list) throws DocumentException {
		for (Element e : list) {
			document.add(e);
		}
	}

}
@Slf4j
public class PdfUtil {


    /**
     *   协议模板
      */
    private ContractTemplateDO contractTemplateDO;

    private PdfHelper pdf;

    private Map<String, Object> data;

    /**
     * 生成pdf路径名
     */
    private String pdfName;

    /**
     * 添加水印的pdf路径名
     */
    private String waterPdfName;


    private File pdfFile;

    private File waterPdfFile;

    /**
     * 文件上传到fast的地址
     */
    private String fileUrl;

    /**
     * 水印文字
     */
    private String watermark;


    private static class Holder{
        private static PdfUtil INSTANCE = new PdfUtil();
    }


    private PdfUtil(){}

    public static PdfUtil getInstance() {
        return Holder.INSTANCE;
    }


    /**
     * 执行生成PDF文件
     */
    public String execute(ContractTemplateDO contractTemplateDO, Map<String, Object> templateData, String watermark, String fileName) {
        this.contractTemplateDO = contractTemplateDO;
        pdfName = CommonUtil.getDir() + fileName + "-" + DateUtil.format2() + ".pdf";
        waterPdfName = CommonUtil.getDir() + fileName + "-" + DateUtil.format2() + "-1.pdf";
        this.pdf = PdfHelper.instance(pdfName);
        this.waterPdfFile = new File(waterPdfName);
        this.data = templateData;
        this.watermark = watermark;
        prepare();
        valid();
        initDate();
        createPdf();
        watermark(watermark);
        //uploadFast();

        return fileUrl;
    }

    /**
     * 预处理
     */
    private void prepare() {
    }

    /**
     * 校验
     */
    private void valid() {
    }

    /**
     * 初始化参数
     */
    private void initDate() {
    }

    /**
     * 创建PDF
     */
    private void createPdf() {
        boolean checkFile = false;
        File pdfFile = new File(pdfName);
        try {
            if (!pdfFile.exists()) {
                pdfFile.mkdir();
            }
            String out = FreemarkerUtil.renderTemplate(contractTemplateDO.getTemplateContent(), this.data);
            ProtocolHelper.templateHtml(out, pdf);
            checkFile = true;
        } catch (IOException e) {
            log.error("解析模板出错",e);
            throw new RuntimeException("解析模板出错");
        } catch (Exception e) {
            log.error("生成pdf出错",e);
        }
        if (!checkFile) {
            throw new RuntimeException("pdf生成的路径不存在...");
        }
        pdf.exportPdf();
    }

    /**
     * 上传到fast
     */
    private void uploadFast() {
        // 上传到文件服务器
        String remoteServerPath = "https://www.xxxx.com/";

        String remoteFilePath = null;

        try {
//            remoteFilePath = FastDfsUtil.upload(fileToByte(waterPdfFile), "pdf");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (StringUtil.isBlank(remoteFilePath)) {
            throw new RuntimeException("文件上传失败,请重新上传!");
        }

        String fileUrl = "";
        // 保存到数据库
        if (remoteServerPath.endsWith("/")) {
            fileUrl = remoteServerPath + remoteFilePath;
        } else {
            fileUrl = remoteServerPath + "/" + remoteFilePath;
        }

        this.fileUrl = fileUrl;
    }

    /**
     * 打印水印
     *
     * @param watermark
     */
    private void watermark(String watermark) {
        WatermarkPrint watermarkPrint = new PDFWatermarkPrint();
        File file = new File(pdfName);
        try {
            watermarkPrint.print(file, new BufferedOutputStream(new FileOutputStream(waterPdfFile)),watermark, DateUtil.format2());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

}
@Slf4j
public class ProtocolHelper {
	/**
	 * 
	 * @param str
	 * @param pdf
	 * @return
	 * @throws IOException
	 * @throws DocumentException
	 */
	protected static void templateHtml(String str, PdfHelper pdf) throws IOException, DocumentException {

		final List<Element> pdfeleList = new ArrayList<Element>();

		ElementHandler elemH = new ElementHandler() {
			@Override
			public void add(final Writable w) {
				if (w instanceof WritableElement) {
					pdfeleList.addAll(((WritableElement) w).elements());
				}
			}
		};

		log.info("Charset.defaultCharset(): {}",Charset.defaultCharset());
		InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream(str.getBytes("UTF-8")), "UTF-8");

		XMLWorkerHelper.getInstance().parseXHtml(elemH, isr);

		List<Element> list = new ArrayList<Element>();

		pdfeleList.forEach(x->{
			if (x instanceof LineSeparator || x instanceof WritableDirectElement) {
				return;
			}
			list.add(x);
		});

		pdf.addHtmlList(list);

	}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没事搞点事做serendipity

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值