实现方式是通过word转pdf然后在转换图片
用到的依赖包
compile "com.documents4j:documents4j-local:1.0.3" compile "com.documents4j:documents4j-transformer-msoffice-word:1.0.3"
实现
package com.viewhigh.epro.svc.util; import com.documents4j.api.DocumentType; import com.documents4j.api.IConverter; import com.documents4j.job.LocalConverter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.PDFRenderer; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * @author qiao * @version 1.0 * @date 2021/8/30 9:43 */ @Slf4j public class WordUtil { /** * word转pdf * * @param wordInputStream word输入流 * @return pdf字节数据 */ public static byte[] wordToPdf(InputStream wordInputStream) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); IConverter converter = LocalConverter.builder().build(); converter.convert(wordInputStream).as(DocumentType.DOC).to(byteArrayOutputStream).as(DocumentType.PDF).execute(); return byteArrayOutputStream.toByteArray(); } /** * pdf转图片 * * @param pdfData pdf字节数据 * @param scale 图片比例(A scale of 1 will render at 72 DPI.) * 根据需求自行调整,数值过大转换会慢 * @return 转换后图片数据的字节数组 */ @SneakyThrows public static List<byte[]> pdfToImage(byte[] pdfData, float scale, boolean isMultiply, Boolean isHorizontal) { try (PDDocument doc = PDDocument.load(pdfData)) { PDFRenderer renderer = new PDFRenderer(doc); int pageCount = doc.getNumberOfPages(); List<BufferedImage> bufferedImageList = new ArrayList<>(); List<byte[]> retList = new ArrayList<>(); for (int i = 0; i < pageCount; i++) { // 第二个参数越大生成图片分辨率越高,转换时间也就越长 BufferedImage image = renderer.renderImage(i, scale); bufferedImageList.add(image); } ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); if (isMultiply) { retList = bufferedImageList.stream().map(item -> { byte[] retBytes = new byte[0]; try { ImageIO.write(item, "PNG", byteArrayOutputStream); retBytes = byteArrayOutputStream.toByteArray(); byteArrayOutputStream.reset(); } catch (IOException e) { log.error("读取单个图片流失败", e); } return retBytes; }).collect(Collectors.toList()); } else { //合成图片 ImageIO.write(mergeImage(isHorizontal, bufferedImageList.toArray(new BufferedImage[0])), "PNG", byteArrayOutputStream); retList.add(byteArrayOutputStream.toByteArray()); } return retList; } } /** * word文档转换为多张图(每页一张) * 说明:如果word文档过大可能会有oom风险,请自行限制大小 * @param wordInputStream word文档输入流 * @param scale 图片比例(A scale of 1 will render at 72 DPI.) * @return 转换后图片数据的字节数组 */ public static List<byte[]> wordToMultipleImage(InputStream wordInputStream, float scale) { return pdfToImage(wordToPdf(wordInputStream), scale, true, null); } /** * word文档转为单张图 * 说明:如果word文档过大可能会有oom风险,请自行限制大小 * @param wordInputStream word文档输入流 * @param scale 图片比例(A scale of 1 will render at 72 DPI.) * @param isHorizontal true-水平 false-垂直 * @return 图片数据字节数组 */ public static byte[] wordToMergeImage(InputStream wordInputStream, float scale, Boolean isHorizontal) { return pdfToImage(wordToPdf(wordInputStream), scale, false, isHorizontal) .stream() .findFirst() .orElse(null); } /** * 合成多个图片 * * @param isHorizontal true-水平 false-垂直 * @param bufferedImages 多张图片buffer * @return 合成后图片buffer */ private static BufferedImage mergeImage(Boolean isHorizontal, BufferedImage... bufferedImages) { if (isHorizontal == null) { isHorizontal = true; } // 生成新图片 BufferedImage destImage; // 计算新图片的长和高 int allw = 0, allh = 0, maxallw = 0, maxallh = 0; // 获取总长、总宽、最长、最宽 for (BufferedImage img : bufferedImages) { allw += img.getWidth(); allh += img.getHeight(); if (img.getWidth() > maxallw) { maxallw = img.getWidth(); } if (img.getHeight() > maxallh) { maxallh = img.getHeight(); } } // 创建新图片 if (isHorizontal) { destImage = new BufferedImage(allw, maxallh, BufferedImage.TYPE_INT_RGB); } else { destImage = new BufferedImage(maxallw, allh, BufferedImage.TYPE_INT_RGB); } // 合并所有子图片到新图片 int wx = 0, wy = 0; for (BufferedImage img : bufferedImages) { int w1 = img.getWidth(); int h1 = img.getHeight(); // 从图片中读取RGB int[] ImageArrayOne = new int[w1 * h1]; ImageArrayOne = img.getRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 逐行扫描图像中各个像素的RGB到数组中 if (isHorizontal) { // 水平方向合并 destImage.setRGB(wx, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB } else { // 垂直方向合并 destImage.setRGB(0, wy, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB } wx += w1; wy += h1; } return destImage; } public static void main(String[] args) { File inputWord = new File("f:/b.doc"); InputStream docxInputStream = null; try { //合成图 // docxInputStream = new FileInputStream(inputWord); // ImageIO.write(ImageIO.read(new ByteArrayInputStream(wordToMergeImage(docxInputStream, 1.25f, false))), "PNG", new File("F:/HHH.PNG")); //多图 docxInputStream = new FileInputStream(inputWord); for (byte[] data : wordToMultipleImage(docxInputStream, 1.25f)) { ImageIO.write(ImageIO.read(new ByteArrayInputStream(data)), "PNG", new File("F:/png/" + System.currentTimeMillis() + ".PNG")); } } catch (Exception e) { e.printStackTrace(); } finally { if (docxInputStream != null) { try { docxInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } }