|
@@ -0,0 +1,266 @@
|
|
|
+package com.caimei365.manager.utils;
|
|
|
+
|
|
|
+import cn.hutool.core.io.FileTypeUtil;
|
|
|
+import com.caimei365.manager.config.utils.UploadImageUtils;
|
|
|
+import com.documents4j.api.DocumentType;
|
|
|
+import com.documents4j.api.IConverter;
|
|
|
+import com.documents4j.job.LocalConverter;
|
|
|
+import com.itextpdf.text.Document;
|
|
|
+import com.itextpdf.text.Element;
|
|
|
+import com.itextpdf.text.pdf.*;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.apache.pdfbox.pdmodel.PDDocument;
|
|
|
+import org.apache.pdfbox.pdmodel.PDPage;
|
|
|
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
|
|
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
|
|
+import org.apache.pdfbox.pdmodel.graphics.blend.BlendMode;
|
|
|
+import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
|
|
+import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
|
|
|
+import org.apache.pdfbox.rendering.PDFRenderer;
|
|
|
+import org.apache.pdfbox.util.Matrix;
|
|
|
+import org.apache.poi.sl.usermodel.PictureData;
|
|
|
+import org.apache.poi.sl.usermodel.PictureData.PictureType;
|
|
|
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
|
|
|
+import org.apache.poi.xslf.usermodel.XSLFPictureShape;
|
|
|
+import org.apache.poi.xslf.usermodel.XSLFSlide;
|
|
|
+import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
|
|
|
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
|
|
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
|
|
|
+import org.dom4j.DocumentException;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.core.env.Environment;
|
|
|
+import org.springframework.core.io.ClassPathResource;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
+import sun.misc.BASE64Encoder;
|
|
|
+
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
+import javax.annotation.Resource;
|
|
|
+import javax.imageio.ImageIO;
|
|
|
+import javax.swing.*;
|
|
|
+import java.awt.*;
|
|
|
+import java.awt.image.BufferedImage;
|
|
|
+import java.io.*;
|
|
|
+import java.net.HttpURLConnection;
|
|
|
+import java.net.URL;
|
|
|
+import java.util.*;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Description
|
|
|
+ *
|
|
|
+ * @author : Charles
|
|
|
+ * @date : 2021/9/18
|
|
|
+ */
|
|
|
+@Component
|
|
|
+public class WaterMarkUtils {
|
|
|
+ @Resource
|
|
|
+ private Environment environment;
|
|
|
+ private static String config;
|
|
|
+ private static String outPath = "/mnt/newdatadrive/data/runtime/jar-instance/manager-api/tempImage/";
|
|
|
+ private static String logoPath = "/mnt/newdatadrive/data/runtime/jar-instance/manager-api/logo/";
|
|
|
+ private final static List<String> imageTypes = Arrays.asList("xbm", "tif", "pjp", "svgz", "jpg", "jpeg", "ico", "tiff", "gif", "svg", "jfif", "webp", "png", "bmp", "pjpeg", "avif");
|
|
|
+ private final static List<String> videoTypes = Arrays.asList("asx", "asf", "mpg", "wmv", "3gp", "mp4", "mov", "avi", "flv");
|
|
|
+
|
|
|
+ @PostConstruct
|
|
|
+ public void setValue() {
|
|
|
+ config = environment.getProperty("cm.config");
|
|
|
+ if ("dev".equals(config)) {
|
|
|
+ outPath = "D:/";
|
|
|
+ logoPath = "D:/";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 日志对象
|
|
|
+ */
|
|
|
+ private static Logger log = LoggerFactory.getLogger(WaterMarkUtils.class);
|
|
|
+ // 水印透明度
|
|
|
+ private static float alpha = 0.15f;
|
|
|
+ // 水印之间的间隔
|
|
|
+ private static final int XMOVE = 150;
|
|
|
+ // 水印之间的间隔
|
|
|
+ private static final int YMOVE = 150;
|
|
|
+
|
|
|
+
|
|
|
+ public static Map<String, Object> addWaterMark(String fileType, String fileUrl) {
|
|
|
+ try {
|
|
|
+ if (imageTypes.contains(fileType)) {
|
|
|
+ return setWaterMarkImage(fileUrl);
|
|
|
+ } else if (videoTypes.contains(fileType)) {
|
|
|
+ return FFMPEG.setVideoWaterMark(fileUrl, outPath);
|
|
|
+ // } else if (fileType.contains("ppt")) {
|
|
|
+ // return setWaterMarkPPT(fileUrl);
|
|
|
+ } else if (fileType.contains("pdf") || fileType.contains("doc") || fileType.contains("xls")||fileType.contains("ppt")) {
|
|
|
+ return setWaterMarkPDF(fileUrl, fileType);
|
|
|
+ } else {
|
|
|
+ throw new NullPointerException("文件格式不正确!");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ log.error("文件添加水印异常!>>>>>>>>>文件后缀:{}>>>>>>>文件地址:{}", fileType, fileUrl);
|
|
|
+ log.error("添加水印异常:" + e);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成水印PDF
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static Map<String, Object> setWaterMarkPDF(String fileUrl, String fileType) throws Exception {
|
|
|
+ String uuid = UUID.randomUUID().toString().replaceAll("-", "");
|
|
|
+ String filePath = outPath + uuid + ".pdf";
|
|
|
+ URL url = new URL(fileUrl);
|
|
|
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
|
+ if (200 != conn.getResponseCode()) {
|
|
|
+ throw new RuntimeException("请求失败了: http response code: " + conn.getResponseCode());
|
|
|
+ }
|
|
|
+ PDDocument doc = null;
|
|
|
+ if (fileType.contains("pdf")) {
|
|
|
+ doc = PDDocument.load(url.openStream());
|
|
|
+ } else if (fileType.contains("doc")) {
|
|
|
+ DocUtil.word2Pdf(url.openStream(), filePath);
|
|
|
+ doc = PDDocument.load(new File(filePath));
|
|
|
+ } else if (fileType.contains("xls")) {
|
|
|
+ PdfUtil.excel2pdf(url.openStream(), filePath, null);
|
|
|
+ doc = PDDocument.load(new File(filePath));
|
|
|
+ } else if (fileType.contains("ppt")) {
|
|
|
+ Ppt2Pdf.ppt2pdf(url.openStream(), new File(filePath));
|
|
|
+ doc = PDDocument.load(new File(filePath));
|
|
|
+ }
|
|
|
+ PDImageXObject pdImage = PDImageXObject.createFromFile(logoPath + "logo.png", doc);
|
|
|
+ PDExtendedGraphicsState gs = new PDExtendedGraphicsState();
|
|
|
+ gs.setNonStrokingAlphaConstant(0.15F);// 设置透明度
|
|
|
+ gs.setAlphaSourceFlag(true);
|
|
|
+ gs.setBlendMode(BlendMode.NORMAL);
|
|
|
+ for (int i = 0; i < doc.getNumberOfPages(); i++) {
|
|
|
+ PDPage page = doc.getPage(i);
|
|
|
+ PDPageContentStream contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true);
|
|
|
+ contentStream.setGraphicsStateParameters(gs);
|
|
|
+ int height = (int) page.getMediaBox().getHeight();
|
|
|
+ int width = (int) page.getMediaBox().getWidth();
|
|
|
+ int size = width > height ? width : height;
|
|
|
+ // 根据纸张大小多次添加, 水印文字成30度角倾斜
|
|
|
+ for (int x = 0; x < size; x += XMOVE) {
|
|
|
+ for (int y = -size / 2; y < size; y += YMOVE) {
|
|
|
+ Matrix matrix = new Matrix();
|
|
|
+ // 旋转
|
|
|
+ matrix.rotate(Math.toRadians(30));
|
|
|
+ // 先移位
|
|
|
+ matrix.translate(x, y);
|
|
|
+ // 修改尺寸(必须在旋转后面,否则会变形)
|
|
|
+ matrix.scale(114, 38);
|
|
|
+ contentStream.drawImage(pdImage, matrix);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ contentStream.close();
|
|
|
+ }
|
|
|
+ doc.save(filePath);
|
|
|
+ doc.close();
|
|
|
+ return OSSUtils.fileUpload(new File(filePath));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private static Map<String, Object> setWaterMarkPPT(String fileUrl) {
|
|
|
+ String uuid = UUID.randomUUID().toString().replaceAll("-", "");
|
|
|
+ String filePath = outPath + uuid + ".pptx";
|
|
|
+ try (FileOutputStream out = new FileOutputStream(filePath)) {
|
|
|
+ URL url = new URL(fileUrl);
|
|
|
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
|
+ if (200 != conn.getResponseCode()) {
|
|
|
+ throw new RuntimeException("请求失败了: http response code: " + conn.getResponseCode());
|
|
|
+ }
|
|
|
+ XMLSlideShow ppt = new XMLSlideShow(url.openStream());
|
|
|
+ BufferedImage waterMarkImageBig = createWaterMarkImageBig(1282, 723);
|
|
|
+ for (XSLFSlide slide : ppt.getSlides()) {
|
|
|
+ XSLFPictureShape slidePicture = slide.createPicture(ppt.addPicture(ImageUtils.bufImg2Bytes(waterMarkImageBig), PictureData.PictureType.PNG));
|
|
|
+ slidePicture.setAnchor(slidePicture.getAnchor());
|
|
|
+ }
|
|
|
+ ppt.write(out);
|
|
|
+ ppt.close();
|
|
|
+ return OSSUtils.fileUpload(new File(filePath));
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ log.error("PPT添加水印异常:" + e);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成水印图片
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static Map<String, Object> setWaterMarkImage(String fileUrl) throws Exception {
|
|
|
+ URL url = new URL(fileUrl);
|
|
|
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
|
+ if (200 != conn.getResponseCode()) {
|
|
|
+ throw new RuntimeException("请求失败了: http response code: " + conn.getResponseCode());
|
|
|
+ }
|
|
|
+ BufferedImage bufferedImage = ImageIO.read(url);
|
|
|
+ ArrayList list = new ArrayList();
|
|
|
+ //合成图片Map
|
|
|
+ HashMap<String, Object> imageFileMap = new HashMap<>();
|
|
|
+ imageFileMap.put("type", 1);
|
|
|
+ imageFileMap.put("image", createWaterMarkImageBig(bufferedImage.getWidth(), bufferedImage.getHeight()));
|
|
|
+ imageFileMap.put("x", 0);
|
|
|
+ imageFileMap.put("y", 0);
|
|
|
+ list.add(imageFileMap);
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("ossUrl", ImageUtils.imageTemplate(bufferedImage, list));
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成水印图片背景
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static BufferedImage createWaterMarkImageBig(int width, int height) throws Exception {
|
|
|
+ BufferedImage bufferedImage = ImageIO.read(new File(logoPath + "logo.png"));
|
|
|
+ BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);// 获取bufferedImage对象
|
|
|
+ Graphics2D g2d = image.createGraphics();
|
|
|
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
|
|
|
+ g2d.rotate(Math.toRadians(-30));
|
|
|
+ int size = width > height ? width : height;
|
|
|
+ for (int x = -size / 2; x < size; x += XMOVE) {
|
|
|
+ for (int y = 0; y < size; y += YMOVE) {
|
|
|
+ g2d.drawImage(bufferedImage, x, y, 114, 38, null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 释放资源
|
|
|
+ g2d.dispose();
|
|
|
+ return image;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 生成水印图片背景
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static File converttoPDF(String filePath,InputStream inputStream , String fileType) throws IOException {
|
|
|
+ PDDocument doc = null;
|
|
|
+ if (fileType.contains("pdf")) {
|
|
|
+ doc = PDDocument.load(inputStream);
|
|
|
+ } else if (fileType.contains("doc")) {
|
|
|
+ InputStream docxInputStream = inputStream;
|
|
|
+ OutputStream outputStream = new FileOutputStream(filePath);
|
|
|
+ IConverter converter = LocalConverter.builder().build();
|
|
|
+ converter.convert(docxInputStream).as(fileType.contains("docx") ? DocumentType.DOCX : DocumentType.DOC).to(outputStream).as(DocumentType.PDF).execute();
|
|
|
+ outputStream.close();
|
|
|
+ doc = PDDocument.load(new File(filePath));
|
|
|
+ } else if (fileType.contains("xls")) {
|
|
|
+ PdfUtil.excel2pdf(inputStream, filePath, null);
|
|
|
+ doc = PDDocument.load(new File(filePath));
|
|
|
+ }
|
|
|
+ doc.save(filePath);
|
|
|
+ doc.close();
|
|
|
+ return new File(filePath);
|
|
|
+ }
|
|
|
+}
|