123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- package com.ruoyi.common.utils;
- import com.ruoyi.common.core.domain.AjaxResult;
- import org.docx4j.TraversalUtil;
- import org.docx4j.XmlUtils;
- import org.docx4j.dml.CTPositiveSize2D;
- import org.docx4j.dml.Graphic;
- import org.docx4j.dml.GraphicData;
- import org.docx4j.dml.picture.Pic;
- import org.docx4j.dml.wordprocessingDrawing.Inline;
- import org.docx4j.finders.RangeFinder;
- import org.docx4j.jaxb.Context;
- import org.docx4j.openpackaging.exceptions.Docx4JException;
- import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
- import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
- import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
- import org.docx4j.wml.*;
- import javax.xml.bind.JAXBElement;
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.util.*;
- /**
- * 给word模板,在需要插入图片(签字)的地方,word中设则书签
- * wordFilePath word 文档路径
- * image 签名BASE64
- * @Author: tjf
- * @Date: 2024/5/15 10:25
- * @Describe:
- */
- public class WordUtil {
- public static AjaxResult wordFilePath(String wordFilePath,String image) {
- try {
- WordprocessingMLPackage wordMLPackage = load(wordFilePath);
- // 提取正文
- MainDocumentPart main = wordMLPackage.getMainDocumentPart();
- Document doc = null;
- doc = main.getContents();
- Body body = doc.getBody();
- // 获取段落
- List<Object> paragraphs = body.getContent();
- // 提取书签并获取书签的游标
- RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
- new TraversalUtil(paragraphs, rt);
- // 遍历书签
- for (CTBookmark bm : rt.getStarts()) {
- System.out.println("name:" + bm.getName());
- // 替换image sign是书签名字
- if ("sign".equals(bm.getName())) {
- addImage(wordMLPackage, bm, image);
- break;
- }
- }
- save(wordMLPackage, wordFilePath);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return AjaxResult.success();
- }
- /**
- * @param wPackage 文档
- * @param bm 书签
- * @param base64String 签名图片base64
- * @throws Exception
- */
- public static void addImage(WordprocessingMLPackage wPackage, CTBookmark bm, String base64String) throws Exception {
- P p = (P) (bm.getParent());
- ObjectFactory factory = Context.getWmlObjectFactory();
- R run = factory.createR();
- // 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片
- // byte[] bytes = IOUtils.toByteArray(new FileInputStream("图片文件路径"));
- //byte[] bytes = getFileBytes(image);
- if (base64String.contains("data:")) {
- int start = base64String.indexOf(",");
- base64String = base64String.substring(start + 1);
- }
- base64String = base64String.replaceAll("\r|\n", "");
- base64String = base64String.trim();
- byte[] bytes = Base64.getDecoder().decode(base64String);
- // 开始创建一个行内图片
- BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);
- // 最后一个是限制图片的宽度,缩放的依据
- Inline newInline = imagePart.createImageInline(null, null, 0, 1, false, 0);
- // 构建绘图
- Drawing drawing = factory.createDrawing();
- // 加入图片段落
- drawing.getAnchorOrInline().add(newInline);
- run.getContent().add(drawing);
- // 清理书签所在数据
- // p.getContent().clear();
- // 加入图片信息
- p.getContent().add(run);
- }
- /**
- * 处理图片适应大小
- * @param cx
- * @param cy
- * @param newCx
- * @param newCy
- */
- public static Map<String, Long> dealCxy(Long cx, Long cy, Long newCx, Long newCy){
- Map<String, Long> map = new HashMap<>();
- Long setCx;
- Long setCy;
- if (newCx > cx){
- if (newCy <= cy){
- setCx = cx;
- setCy = newCy/(newCx/cx);
- } else {
- if ((newCx/cx) > (newCy/cy)){
- setCx = cx;
- setCy = newCy/(newCx/cx);
- } else {
- setCy = cy;
- setCx = newCx/(newCy/cy);
- }
- }
- } else { // newCx < cx
- if (newCy > cy) {
- setCx = cx;
- setCy = newCy * (cx/newCx);
- } else {
- if ((cx/newCx) > (cy/newCy)) {
- setCx = cx;
- setCy = newCy *(cx/newCx);
- } else {
- setCy = cy;
- setCx = newCy * (cy/newCy);
- }
- }
- }
- map.put("setCx",setCx);
- map.put("setCy",setCy);
- return map;
- }
- /**
- * 得到指定类型的元素
- * @param obj
- * @param toSearch
- * @return
- */
- public static List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
- List<Object> result = new ArrayList<>();
- if (obj instanceof JAXBElement)
- obj = ((JAXBElement<?>) obj).getValue();
- if (obj.getClass().equals(toSearch))
- result.add(obj);
- else if (obj instanceof ContentAccessor) {
- List<?> children = ((ContentAccessor) obj).getContent();
- for (Object child : children) {
- result.addAll(getAllElementFromObject(child, toSearch));
- }
- }
- return result;
- }
- /**
- * 构建文件
- */
- public static WordprocessingMLPackage build() throws Exception {
- return WordprocessingMLPackage.createPackage();
- }
- /**
- * 读取存在的word文件
- *
- * @param wordFilePath word文件路径
- */
- public static WordprocessingMLPackage load(String wordFilePath) throws Exception {
- return WordprocessingMLPackage.load(new File(wordFilePath));
- }
- /**
- * 保存
- *
- * @param wordMLPackage word
- */
- public static void save(WordprocessingMLPackage wordMLPackage, String wordFilePath) throws Exception {
- wordMLPackage.save(new File(wordFilePath));
- }
- /**
- * 将图片转为Base64数组
- *
- * @param filePath
- * @return
- * @throws Exception
- */
- public static byte[] getFileBytes(String filePath) throws Exception {
- File file = new File(filePath);
- if (!file.exists()) {
- throw new Exception("文件不存在!");
- }
- byte[] data = null;
- try (FileInputStream fis = new FileInputStream(file); ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
- int len;
- byte[] buffer = new byte[1024];
- while ((len = fis.read(buffer)) != -1) {
- baos.write(buffer, 0, len);
- }
- data = baos.toByteArray();
- }
- return data;
- }
- }
|