JAVA POI富文本导出WORD添加水印
背景
在java 开发中 特别是OA开发中,经常会遇到导出word的操作,同时随时AI时代的到来,很多导出文档都需要增加水印标识,用来追溯数据生产方。
本文将介绍如何通过操作POI 来实现导出富文本到word ,并在文档中追加水印功能。
代码实现
导入POM
首先我们需要导入需要引用的POM文件
org.apache.poi
poi
4.1.2
org.apache.poi
poi-ooxml
4.1.2
commons-io
commons-io
2.12.0
org.jsoup
jsoup
1.14.3
commons-io包为poi依赖如果缺失,会提示NotFoundClass 。
jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
将html转换为dom文档
采用Jsoup处理类来实现将html内容转换为dom结构,便于后续操作
public static Document convertToDom(String htmlContent) {
Document doc = Jsoup.parse(htmlContent, "UTF-8");
return doc;
}
基于POI处理dom内容
首先解析dom中的body 获取body下的所有元素
再根据Element 中解析的tagName来分别处理在word文档中不同样式,也可以Element.attr属性来获取html中的自定义属性,类似js或者xml node节点的操作
针对图片由于html中的图片都来源于网络,所以本文基于实际操作,将图片转换为base64编码,保证图片在word中正确展示
/**
* 解析Document 并处理 body下的所有Elements
*
* @param htmlDocument
* @param wordDocument
* @throws IOException
* @throws InvalidFormatException
*/
public static void parseDocument(Document htmlDocument, XWPFDocument wordDocument) throws IOException, InvalidFormatException {
Elements elements = htmlDocument.body().children();
for (Element element : elements) {
parseElement(element, wordDocument);
}
}
/**
* 解析Elements 处理标签中指定tagName
*
* @param element
* @param wordDocument
* @throws IOException
* @throws InvalidFormatException
*/
private static void parseElement(Element element, XWPFDocument wordDocument) throws IOException, InvalidFormatException {
// 处理元素类型,例如、
等 String tagName = element.tagName(); switch (tagName) { case "p": // 处理段落 // 也可以根据 element.attr来处理不通css样式的文字 String text = element.text(); XWPFRun runP = wordDocument.createParagraph().createRun(); runP.setText(text); break; case "h1": case "h2": // 处理标题1 可以自定义样式 //此处可以处理不同标签 String heading1Text = element.text(); XWPFRun runH1 = wordDocument.createParagraph().createRun(); runH1.setText(heading1Text); runH1.setBold(true); runH1.setFontSize(16); break; case "img": //处理图片,由于html的图片来源为网络图片,所以此处将网络图片转换为base64编码,并插入word文档 XWPFRun run = wordDocument.createParagraph().createRun(); String src = element.attr("src").toString(); byte[] imageData = org.apache.commons.codec.binary.Base64.decodeBase64(ImageToBase64ByOnline(src)); run.addPicture(new ByteArrayInputStream(imageData), XWPFDocument.PICTURE_TYPE_JPEG, "image", Units.toEMU(300), Units.toEMU(200)); break; default: break; } // 递归处理子元素 Elements children = element.children(); for (Element child : children) { parseElement(child, wordDocument); } }
基于POM添加水印
调用POI 的 XWPFHeaderFooterPolicy.createWatermark api可以添加水印,但是添加之后会存在后续编辑新增段落水印不会新增,同时样式不能调整,位置为水平居中效果不是很好看,基于系统createWatermark水印效果,本方法提供了增强具体可以看代码
/**
* 添加水印,在调用系统api添加水印的同时,并针对系统水印的确定进行额外处理
*
* @param doc
* @param markStr
*/
public static void addWatermark(XWPFDocument doc, String markStr) {
XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy();
if (headerFooterPolicy == null) {
//兼容处理
headerFooterPolicy = doc.createHeaderFooterPolicy();
}
//调用API添加水印,效果不好为水平居中
headerFooterPolicy.createWatermark(markStr);
//处理后续文档更新水印逻辑
XWPFHeader header = headerFooterPolicy.getHeader(XWPFHeaderFooterPolicy.DEFAULT);
XWPFParagraph paragraph;
paragraph = header.getParagraphArray(0);
//设置水印样式和位置,保持倾斜角度更好看和实用
paragraph.getCTP().newCursor();
org.apache.xmlbeans.XmlObject[] xmlobjects = paragraph.getCTP().getRArray(0).getPictArray(0).selectChildren(
new javax.xml.namespace.QName("urn:schemas-microsoft-com:vml", "shape"));
if (xmlobjects.length > 0) {
CTShape ctshape = (CTShape) xmlobjects[0];
ctshape.setFillcolor("#C0C0C0");
ctshape.setStyle(ctshape.getStyle() + ";rotation:315");
}
}
完整代码
package com.dayouz.word;
import com.microsoft.schemas.vml.CTShape;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* @author dayouz
* @classname WordUtil
* @desc JAVA POI 实现 富文本导出 WORD 和添加水印
*/
public class WordUtil {
/**
* 将html内容转换为Document结构
*
* @param htmlContent
* @return
*/
public static Document convertToDom(String htmlContent) {
Document doc = Jsoup.parse(htmlContent, "UTF-8");
return doc;
}
/**
* 解析Document 并处理 body下的所有Elements
*
* @param htmlDocument
* @param wordDocument
* @throws IOException
* @throws InvalidFormatException
*/
public static void parseDocument(Document htmlDocument, XWPFDocument wordDocument) throws IOException, InvalidFormatException {
Elements elements = htmlDocument.body().children();
for (Element element : elements) {
parseElement(element, wordDocument);
}
}
/**
* 解析Elements 处理标签中指定tagName
*
* @param element
* @param wordDocument
* @throws IOException
* @throws InvalidFormatException
*/
private static void parseElement(Element element, XWPFDocument wordDocument) throws IOException, InvalidFormatException {
// 处理元素类型,例如、
等 String tagName = element.tagName(); switch (tagName) { case "p": // 处理段落 // 也可以根据 element.attr来处理不通css样式的文字 String text = element.text(); XWPFRun runP = wordDocument.createParagraph().createRun(); runP.setText(text); break; case "h1": case "h2": // 处理标题1 可以自定义样式 //此处可以处理不同标签 String heading1Text = element.text(); XWPFRun runH1 = wordDocument.createParagraph().createRun(); runH1.setText(heading1Text); runH1.setBold(true); runH1.setFontSize(16); break; case "img": //处理图片,由于html的图片来源为网络图片,所以此处将网络图片转换为base64编码,并插入word文档 XWPFRun run = wordDocument.createParagraph().createRun(); String src = element.attr("src").toString(); byte[] imageData = imageToBase64(src); run.addPicture(new ByteArrayInputStream(imageData), XWPFDocument.PICTURE_TYPE_JPEG, "image", Units.toEMU(300), Units.toEMU(200)); break; default: break; } // 递归处理子元素 Elements children = element.children(); for (Element child : children) { parseElement(child, wordDocument); } } /** * 添加水印,在调用系统api添加水印的同时,并针对系统水印的确定进行额外处理 * * @param doc * @param markStr */ public static void addWatermark(XWPFDocument doc, String markStr) { XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy(); if (headerFooterPolicy == null) { //兼容处理 headerFooterPolicy = doc.createHeaderFooterPolicy(); } //调用API添加水印,效果不好为水平居中 headerFooterPolicy.createWatermark(markStr); //处理后续文档更新水印逻辑 XWPFHeader header = headerFooterPolicy.getHeader(XWPFHeaderFooterPolicy.DEFAULT); XWPFParagraph paragraph; paragraph = header.getParagraphArray(0); //设置水印样式和位置,保持倾斜角度更好看和实用 paragraph.getCTP().newCursor(); org.apache.xmlbeans.XmlObject[] xmlobjects = paragraph.getCTP().getRArray(0).getPictArray(0).selectChildren( new javax.xml.namespace.QName("urn:schemas-microsoft-com:vml", "shape")); if (xmlobjects.length > 0) { CTShape ctshape = (CTShape) xmlobjects[0]; ctshape.setFillcolor("#C0C0C0"); ctshape.setStyle(ctshape.getStyle() + ";rotation:315"); } } /** * 在线图片转换成base64字符串 * * @param imgURL 图片地址 * @return */ private static byte[] imageToBase64(String imgURL) { ByteArrayOutputStream data = new ByteArrayOutputStream(); try { // 创建URL URL url = new URL(imgURL); byte[] by = new byte[1024]; // 创建链接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); InputStream is = conn.getInputStream(); // 将内容读取内存中 int len = -1; while ((len = is.read(by)) != -1) { data.write(by, 0, len); } // 关闭流 is.close(); } catch (IOException e) { e.printStackTrace(); } return data.toByteArray(); } public static void main(String[] args) throws IOException, InvalidFormatException { //初始化文档 XWPFDocument doc = new XWPFDocument(new FileInputStream("input.docx")); //将html转换为dom Document document = convertToDom(""); //处理dom添加到word parseDocument(document, doc); //添加水印 addWatermark(doc, "CSDN"); //保存本地 doc.write(new FileOutputStream("output.docx")); doc.close(); }}
以上内容就是java 通过poi来实现富文本导出到word文档,针对图片也给力处理方式demo,特别是针对水印功能,针对系统函数的功能和美观上的缺失做了方法扩展,
本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://net2asp.com/4256960781.html
