WordUtil.java 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. package com.ruoyi.common.utils;
  2. import com.ruoyi.common.core.domain.AjaxResult;
  3. import org.docx4j.TraversalUtil;
  4. import org.docx4j.XmlUtils;
  5. import org.docx4j.dml.CTPositiveSize2D;
  6. import org.docx4j.dml.Graphic;
  7. import org.docx4j.dml.GraphicData;
  8. import org.docx4j.dml.picture.Pic;
  9. import org.docx4j.dml.wordprocessingDrawing.Inline;
  10. import org.docx4j.finders.RangeFinder;
  11. import org.docx4j.jaxb.Context;
  12. import org.docx4j.openpackaging.exceptions.Docx4JException;
  13. import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
  14. import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
  15. import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
  16. import org.docx4j.wml.*;
  17. import javax.xml.bind.JAXBElement;
  18. import java.io.ByteArrayOutputStream;
  19. import java.io.File;
  20. import java.io.FileInputStream;
  21. import java.util.*;
  22. /**
  23. * 给word模板,在需要插入图片(签字)的地方,word中设则书签
  24. * wordFilePath word 文档路径
  25. * image 签名BASE64
  26. * @Author: tjf
  27. * @Date: 2024/5/15 10:25
  28. * @Describe:
  29. */
  30. public class WordUtil {
  31. public static AjaxResult wordFilePath(String wordFilePath,String image) {
  32. try {
  33. WordprocessingMLPackage wordMLPackage = load(wordFilePath);
  34. // 提取正文
  35. MainDocumentPart main = wordMLPackage.getMainDocumentPart();
  36. Document doc = null;
  37. doc = main.getContents();
  38. Body body = doc.getBody();
  39. // 获取段落
  40. List<Object> paragraphs = body.getContent();
  41. // 提取书签并获取书签的游标
  42. RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
  43. new TraversalUtil(paragraphs, rt);
  44. // 遍历书签
  45. for (CTBookmark bm : rt.getStarts()) {
  46. System.out.println("name:" + bm.getName());
  47. // 替换image sign是书签名字
  48. if ("sign".equals(bm.getName())) {
  49. addImage(wordMLPackage, bm, image);
  50. break;
  51. }
  52. }
  53. save(wordMLPackage, wordFilePath);
  54. } catch (Exception e) {
  55. e.printStackTrace();
  56. }
  57. return AjaxResult.success();
  58. }
  59. /**
  60. * @param wPackage 文档
  61. * @param bm 书签
  62. * @param base64String 签名图片base64
  63. * @throws Exception
  64. */
  65. public static void addImage(WordprocessingMLPackage wPackage, CTBookmark bm, String base64String) throws Exception {
  66. P p = (P) (bm.getParent());
  67. ObjectFactory factory = Context.getWmlObjectFactory();
  68. R run = factory.createR();
  69. // 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片
  70. // byte[] bytes = IOUtils.toByteArray(new FileInputStream("图片文件路径"));
  71. //byte[] bytes = getFileBytes(image);
  72. if (base64String.contains("data:")) {
  73. int start = base64String.indexOf(",");
  74. base64String = base64String.substring(start + 1);
  75. }
  76. base64String = base64String.replaceAll("\r|\n", "");
  77. base64String = base64String.trim();
  78. byte[] bytes = Base64.getDecoder().decode(base64String);
  79. // 开始创建一个行内图片
  80. BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);
  81. // 最后一个是限制图片的宽度,缩放的依据
  82. Inline newInline = imagePart.createImageInline(null, null, 0, 1, false, 0);
  83. // 构建绘图
  84. Drawing drawing = factory.createDrawing();
  85. // 加入图片段落
  86. drawing.getAnchorOrInline().add(newInline);
  87. run.getContent().add(drawing);
  88. // 清理书签所在数据
  89. // p.getContent().clear();
  90. // 加入图片信息
  91. p.getContent().add(run);
  92. }
  93. /**
  94. * 处理图片适应大小
  95. * @param cx
  96. * @param cy
  97. * @param newCx
  98. * @param newCy
  99. */
  100. public static Map<String, Long> dealCxy(Long cx, Long cy, Long newCx, Long newCy){
  101. Map<String, Long> map = new HashMap<>();
  102. Long setCx;
  103. Long setCy;
  104. if (newCx > cx){
  105. if (newCy <= cy){
  106. setCx = cx;
  107. setCy = newCy/(newCx/cx);
  108. } else {
  109. if ((newCx/cx) > (newCy/cy)){
  110. setCx = cx;
  111. setCy = newCy/(newCx/cx);
  112. } else {
  113. setCy = cy;
  114. setCx = newCx/(newCy/cy);
  115. }
  116. }
  117. } else { // newCx < cx
  118. if (newCy > cy) {
  119. setCx = cx;
  120. setCy = newCy * (cx/newCx);
  121. } else {
  122. if ((cx/newCx) > (cy/newCy)) {
  123. setCx = cx;
  124. setCy = newCy *(cx/newCx);
  125. } else {
  126. setCy = cy;
  127. setCx = newCy * (cy/newCy);
  128. }
  129. }
  130. }
  131. map.put("setCx",setCx);
  132. map.put("setCy",setCy);
  133. return map;
  134. }
  135. /**
  136. * 得到指定类型的元素
  137. * @param obj
  138. * @param toSearch
  139. * @return
  140. */
  141. public static List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
  142. List<Object> result = new ArrayList<>();
  143. if (obj instanceof JAXBElement)
  144. obj = ((JAXBElement<?>) obj).getValue();
  145. if (obj.getClass().equals(toSearch))
  146. result.add(obj);
  147. else if (obj instanceof ContentAccessor) {
  148. List<?> children = ((ContentAccessor) obj).getContent();
  149. for (Object child : children) {
  150. result.addAll(getAllElementFromObject(child, toSearch));
  151. }
  152. }
  153. return result;
  154. }
  155. /**
  156. * 构建文件
  157. */
  158. public static WordprocessingMLPackage build() throws Exception {
  159. return WordprocessingMLPackage.createPackage();
  160. }
  161. /**
  162. * 读取存在的word文件
  163. *
  164. * @param wordFilePath word文件路径
  165. */
  166. public static WordprocessingMLPackage load(String wordFilePath) throws Exception {
  167. return WordprocessingMLPackage.load(new File(wordFilePath));
  168. }
  169. /**
  170. * 保存
  171. *
  172. * @param wordMLPackage word
  173. */
  174. public static void save(WordprocessingMLPackage wordMLPackage, String wordFilePath) throws Exception {
  175. wordMLPackage.save(new File(wordFilePath));
  176. }
  177. /**
  178. * 将图片转为Base64数组
  179. *
  180. * @param filePath
  181. * @return
  182. * @throws Exception
  183. */
  184. public static byte[] getFileBytes(String filePath) throws Exception {
  185. File file = new File(filePath);
  186. if (!file.exists()) {
  187. throw new Exception("文件不存在!");
  188. }
  189. byte[] data = null;
  190. try (FileInputStream fis = new FileInputStream(file); ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
  191. int len;
  192. byte[] buffer = new byte[1024];
  193. while ((len = fis.read(buffer)) != -1) {
  194. baos.write(buffer, 0, len);
  195. }
  196. data = baos.toByteArray();
  197. }
  198. return data;
  199. }
  200. }