java添加图片水印工具类
支持为xls、xlsx、doc、docx、ppt、pptx、pdf、各类图片文件、视频文件 添加png图片水印。
效果图
依赖工具包:
* pdf - itext
* word ppt - spire (解除页数限制)
* excel - poi
* 视频 - ffmpeg
maven坐标:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.0</version>
</dependency>
<!-- easypoi -->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.4</version>
</dependency>
<!-- pdf加水印-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.office.free</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-all-deps</artifactId>
<version>3.0.1</version>
<exclusions>
<!-- 排除windows 32位系统 -->
<exclusion>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-win32</artifactId>
</exclusion>
<!-- 排除linux 32位系统 -->
<exclusion>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-linux32</artifactId>
</exclusion>
<!-- 排除Mac系统-->
<exclusion>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-osx64</artifactId>
</exclusion>
</exclusions>
</dependency>
代码
1. 核心工具类
import cn.hutool.core.io.FileUtil;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.PictureWatermark;
import com.spire.presentation.*;
import com.spire.presentation.collections.SlideCollection;
import com.spire.presentation.drawing.FillFormatType;
import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
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.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import ws.schild.jave.info.VideoSize;
import ws.schild.jave.process.ProcessWrapper;
import ws.schild.jave.process.ffmpeg.DefaultFFMPEGLocator;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Dimension2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import static java.lang.Long.SIZE;
/**
* 添加水印工具类
* pdf - itext
* doc/docx ppt/pptx - spire
* excel - poi
* 视频 - ffmpeg
*
* @author narnew
*/
public class WatermarkUtil {
private static final Logger LOG = LoggerFactory.getLogger(WatermarkUtil.class);
/**
* 水印内容
*/
public static final String WATER_MARK_TEXT = "水印文字";
/**
* 字体
* 初步筛选出Graphics2D支持中文的字体有:
* Arial Unicode MS、Dialog、DialogInput、Microsoft JhengHei、Microsoft JhengHei Light、Microsoft JhengHei UI、Microsoft JhengHei UI Light、Microsoft YaHei UI、Microsoft YaHei UI Light、
* MS Gothic、MS PGothic、MS UI Gothic、SansSerif、Serif、仿宋、华文中宋、华文仿宋、华文宋体、华文彩云、华文新魏、华文楷体、华文琥珀、华文细黑、华文行楷、华文隶书、宋体、幼圆、微软雅黑、微软雅黑 Light、新宋体、
* 方正姚体、方正舒体、楷体、等线、等线 Light、隶书、黑体
* ————————————————
* 原文链接:
*/
public static final String FONT_NAME = "Serif";
private static final String DEFAULT_MARK_IMG_PATH = "static/template/watermark.png";
/**
* @param filePath 生成临时保存路径
* @return 临时保存路径
*/
public static String getSavePath(String filePath) {
return filePath.substring(0, filePath.lastIndexOf("/") + 1) + "out_" + System.currentTimeMillis() + "_" + StrUtil.subAfter(filePath, "/", true);
}
/**
* 根据文字构造水印图片
*
* @param text 水印文本内容
* @return {@link BufferedImage}
*/
@Deprecated
public static BufferedImage createWatermarkImage(String text, int width, int height) {
Font font = new Font(FONT_NAME, Font.PLAIN, height / 30);
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 绘制透明背景
Graphics2D g = image.createGraphics();
image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
g.dispose();
// 背景透明 结束
g = image.createGraphics();
// 1.0f为透明度 ,值从0-1.0,依次变得不透明
g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, 0.5f));
// 设定画笔颜色
g.setColor(new Color(243, 28, 28));
// 设置画笔字体
g.setFont(font);
// 设定倾斜度
g.shear(0.1, -0.26);
// 设置字体平滑 消除文字锯齿
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//消除画图锯齿
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//相当于margin-top
int y = 8 * font.getSize();
int x = 0;
// 画出字符串
for (int i = 0; i < 5; i++) {
g.drawString(text, x, y);
y += 10 * font.getSize();
}
g.dispose();
return image;
}
/**
* 用默认图片自适应文件尺寸
*/
public static BufferedImage readAndResizePNGImage(int width, int height) {
return readAndResizePNGImage(width, height, DEFAULT_MARK_IMG_PATH);
}
/**
* 根据宽高重新调整水印图片比例大小
*
* @param width 文件宽
* @param height 文件高
* @param markImgPath 水印图片路径
* @return BufferedImage
*/
public static BufferedImage readAndResizePNGImage(int width, int height, String markImgPath) {
double heightNew = height;
double widthNew = width;
double scale;
ClassPathResource resource = new ClassPathResource(markImgPath);
try {
// 读取输入的PNG图片
BufferedImage originalImage = ImageIO.read(resource.getInputStream());
int MARK_HEIGHT = originalImage.getHeight();
int MARK_WIDTH = originalImage.getWidth();
//计算缩放比例
//取较长的一边
if (width * MARK_HEIGHT < height * MARK_WIDTH) {
scale = heightNew / MARK_HEIGHT;
widthNew = scale * MARK_WIDTH;
} else {
scale = widthNew / MARK_WIDTH;
heightNew = (scale * MARK_HEIGHT);
}
//缩放
BufferedImage scaledImage = new BufferedImage((int) widthNew, (int) heightNew, originalImage.getType());
Graphics graphics = scaledImage.createGraphics();
graphics.drawImage(originalImage, 0, 0, (int) widthNew, (int) heightNew, null);
graphics.dispose();
// 创建一个透明的新图片,宽度和高度为新指定的尺寸
BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// 获取新图片的Graphics2D对象,用于绘制新图片
Graphics2D g2d = resizedImage.createGraphics();
// 设置Graphics2D对象的绘制质量为高质量
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
// 循环绘制原始图片,实现平铺效果
for (int y = 0; y < height; y += scaledImage.getHeight()) {
for (int x = 0; x < width; x += scaledImage.getWidth()) {
g2d.drawImage(scaledImage, x, y, null);
}
}
// 释放资源
g2d.dispose();
return resizedImage;
} catch (IOException e) {
LOG.error(e.getMessage(), e);
throw new CoreException(ErrorCodeEnum.SYS_ERROR);
}
}
/**
* excel文件添加水印图片
* @param filePath 文件路径
* @throws IOException io操作异常
*/
public static String setWaterMarkToExcel(String filePath) throws IOException {
ClassPathResource resource = new ClassPathResource(DEFAULT_MARK_IMG_PATH);
BufferedImage bfi = ImageIO.read(resource.getInputStream());
String savePath = FileProcessingUtil.getSavePath(filePath);
FileOutputStream os = new FileOutputStream(savePath);
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
ImageIO.write(bfi, "png", byteArrayOut);
String type = ExcelFileUtil.getType(filePath);
if ("xls".equals(type)) {
// 创建新的.xlsx文件
try (FileInputStream fis = new FileInputStream(filePath);
XSSFWorkbook newWorkbook = new XSSFWorkbook()) {
// 读取旧版的.xls文件
Workbook oldWorkbook = WorkbookFactory.create(fis);
// 读取旧版的Sheet并复制到新的Workbook中
for (int i = 0; i < oldWorkbook.getNumberOfSheets(); i++) {
HSSFSheet oldSheet = (HSSFSheet) oldWorkbook.getSheetAt(i);
XSSFSheet newSheet = newWorkbook.createSheet(oldSheet.getSheetName());
ExcelFileUtil.copySheets(oldSheet, newSheet);
}
setWaterMarkToSheet(os, byteArrayOut, newWorkbook);
}
}
if ("xlsx".equals(type)) {
//xlsx
try (XSSFWorkbook workbook = new XSSFWorkbook(filePath)) {
setWaterMarkToSheet(os, byteArrayOut, workbook);
}
}
return savePath;
}
private static void setWaterMarkToSheet(FileOutputStream os, ByteArrayOutputStream byteArrayOut, XSSFWorkbook workbook) throws IOException {
int pictureIdx = workbook.addPicture(byteArrayOut.toByteArray(), Workbook.PICTURE_TYPE_PNG);
POIXMLDocumentPart poixmlDocumentPart = workbook.getAllPictures().get(pictureIdx);
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
XSSFSheet xssfSheet = workbook.getSheetAt(i);
PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
String relType = XSSFRelation.IMAGES.getRelation();
PackageRelationship pr = xssfSheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
xssfSheet.getCTWorksheet().addNewPicture().setId(pr.getId());
}
workbook.write(os);
}
/**
* word文档设置水印图片
*
* @param filePath 文件路径
* @throws IOException ioexception
*/
public static String setWaterMarkToWord(String filePath) throws IOException {
Document document = new Document();
document.loadFromFile(filePath);
Dimension2D pageSize = document.getLastSection().getPageSetup().getPageSize();
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedImage bfi = readAndResizePNGImage((int)pageSize.getWidth(), (int) (pageSize.getHeight()));
ImageIO.write(bfi, "png", out);
PictureWatermark picture = new PictureWatermark();
InputStream input = new ByteArrayInputStream(out.toByteArray());
//设置图片
picture.setPicture(input);
//是否冲刷,true->图片色彩变淡,false->原色彩
picture.isWashout(false);
//保存文档
document.setWatermark(picture);
String savePath = FileProcessingUtil.getSavePath(filePath);
document.saveToFile(savePath, FileFormat.Docx);
return savePath;
}
/**
* pdf加水印图片
*
* @param filePath 文件路径
* @return {@link String}
* @throws IOException ioexception
* @throws DocumentException 文件异常
*/
public static String setWaterMarkToPdf(String filePath) throws IOException, DocumentException {
PdfReader reader = new PdfReader(filePath);
//获取首页尺寸 定制水印大小
com.itextpdf.text.Rectangle ps = reader.getPageSize(1);
// BufferedImage bfi = createWatermarkImage(WATER_MARK_TEXT, (int) ps.getWidth(), (int) ps.getHeight());
BufferedImage bfi = readAndResizePNGImage((int) ps.getWidth(), (int) ps.getHeight());
//保存路径
String savePath = FileProcessingUtil.getSavePath(filePath);
PdfStamper stamper = new PdfStamper(reader, Files.newOutputStream(Paths.get(savePath)));
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(bfi, "png", out);
//将图片放入pdf中
com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(out.toByteArray());
//获取pdf页数
int num = reader.getNumberOfPages();
com.itextpdf.text.Rectangle pageSize;
float width;
float height;
for (int i = 1; i < num + 1; i++) {
//得到页面大小
pageSize = reader.getPageSize(i);
width = pageSize.getWidth();
height = pageSize.getHeight();
//水印图片设置在内容之上,之下用getUnderContent
// PdfContentByte pdfContentByte = stamper.getUnderContent(i);
PdfContentByte pdfContentByte = stamper.getOverContent(i);
//设置图片的位置,参数Image.UNDERLYING是作为文字的背景显示。
image.setAlignment(com.itextpdf.text.Image.UNDERLYING);
//设置图片的绝对位置
image.scaleToFit(width, height);
image.setAbsolutePosition((width - image.getScaledWidth()) / 2, (height - image.getScaledHeight()) / 2);
pdfContentByte.addImage(image);
}
stamper.close();
reader.close();
return savePath;
}
/**
* PPT设置水印图片
*
* @param filePath 原始文件路径
* @return 新文件保存路径
*/
public static String setPPTWaterMarkPic(String filePath) {
String savePath = FileProcessingUtil.getSavePath(filePath);
if (PowerPointTypeDetectionUtil.isPpt(filePath)) {
//ppt
try (HSLFSlideShow ppt = new HSLFSlideShow(new HSLFSlideShowImpl(filePath));
FileOutputStream out = new FileOutputStream(savePath)) {
java.awt.Dimension pgsize = ppt.getPageSize();
BufferedImage bfi = readAndResizePNGImage(pgsize.width, pgsize.height);
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
ImageIO.write(bfi, "png", byteArrayOut);
HSLFPictureData pd = ppt.addPicture(byteArrayOut.toByteArray(), PictureData.PictureType.JPEG);
HSLFPictureShape pictNew = new HSLFPictureShape(pd);
pictNew.setAnchor(new java.awt.Rectangle(0, 0, pgsize.width, pgsize.height));
for (HSLFSlide slide : ppt.getSlides()) {
slide.addShape(pictNew);
}
ppt.write(out);
} catch (IOException e) {
LOG.error(e.getMessage(), e);
throw new CoreException(ErrorCodeEnum.FILE_NOT_EXISTS);
}
} else {
//pptx
try (
XMLSlideShow slideShow = new XMLSlideShow(Files.newInputStream(Paths.get(filePath)));
FileOutputStream out = new FileOutputStream(savePath)
) {
int height = (int) slideShow.getPageSize().getHeight();
int width = (int) slideShow.getPageSize().getWidth();
//获取水印
BufferedImage bfi = readAndResizePNGImage(width, height);
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
ImageIO.write(bfi, "png", byteArrayOut);
PictureData pictureData = slideShow.addPicture(byteArrayOut.toByteArray(), PictureData.PictureType.PNG);
for (XSLFSlide slide : slideShow.getSlides()) {
XSLFPictureShape pictureShape = slide.createPicture(pictureData);
pictureShape.setAnchor(new java.awt.Rectangle(0, 0, width, height));
}
slideShow.write(out);
} catch (IOException e) {
LOG.error("生成PPT文件失败:" + e,e);
throw new CoreException(ErrorCodeEnum.FILE_SAVE_FAIL, "生成PPT文件失败");
}
}
return savePath;
}
/**
* ppt加水印文字
*
* @param filePath 原始文件路径
* @return {@link String} 新文件保存路径
*/
public static String setWaterMarkToPpt(String filePath) throws Exception {
Presentation ppt = new Presentation();
ppt.loadFromFile(filePath);
//获取指定幻灯片
SlideCollection slides = ppt.getSlides();
//获取PPT宽高
double widthOrig = ppt.getSlideSize().getSize().getWidth();
//设置文本水印文本宽和高
int width = 180;
int height = 50;
for (int k = 0; k < slides.size(); k++) {
//起始坐标
float x = (float) ((widthOrig / 3) - 100 - (2 * width / 3));
float y = 40;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//绘制文本,设置文本格式并将其添加到第一张幻灯片
Rectangle2D.Double rect = new Rectangle2D.Double(x, y, width, height);
IAutoShape shape = slides.get(k).getShapes().appendShape(ShapeType.RECTANGLE, rect);
shape.getFill().setFillType(FillFormatType.NONE);
shape.getShapeStyle().getLineColor().setColor(Color.white);
shape.setRotation(-30);
shape.getLocking().setSelectionProtection(true);
shape.getLine().setFillType(FillFormatType.NONE);
shape.getTextFrame().setText(WATER_MARK_TEXT);
shape.setShapeArrange(ShapeAlignmentEnum.ShapeArrange.BringToFront);
PortionEx textRange = shape.getTextFrame().getTextRange();
textRange.getFill().setFillType(FillFormatType.SOLID);
textRange.getFill().getSolidColor().setColor(Color.pink);
textRange.setFontHeight(20);
x += (100 + widthOrig / 6);
}
x = (float) ((widthOrig / 3) - 100 - (2 * width / 3));
y += (100 + ppt.getSlideSize().getSize().getHeight() / 7);
}
}
//保存文档
String savePath = FileProcessingUtil.getSavePath(filePath);
ppt.saveToFile(savePath, com.spire.presentation.FileFormat.PPSX_2013);
ppt.dispose();
return savePath;
}
/**
* 图片加水印
*
* @param filePath 文件路径
* @return {@link String}
*/
public static String setWaterMarkToImg(String filePath) throws IOException {
//获取画布
BufferedImage read = ImageIO.read(new File(filePath));
Graphics2D graphics = read.createGraphics();
//缩放水印图片
int width = read.getWidth();
int height = read.getHeight();
BufferedImage bfi = readAndResizePNGImage(width, height);
//设置比例
float f = 1.0f;
//获取缩放后的宽度
int w = (int) (width * f);
int h = (int) (height * f);
//缩放图片
// Image image = bfi.getScaledInstance(w, h, Image.SCALE_SMOOTH);
//alpha 设置透明度,0->1,逐渐不透明
//SRC_ATOP 重叠模式:源置顶,取并集
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0F));
//添加水印并设置在图片的右下角
graphics.drawImage(bfi, read.getWidth() - w, read.getHeight() - h, null);
//释放资源
graphics.dispose();
//保存图片
String savePath = FileProcessingUtil.getSavePath(filePath);
ImageIO.write(read, filePath.substring(filePath.lastIndexOf(".") + 1), new File(savePath));
return savePath;
}
/**
* 视频加水印
*
* @param videoPath 视频源地址
* @return 保存路径
*/
public static String setWaterMarkToVideo(String videoPath) {
//获取原视频分辨率 以生成适配水印图案
VideoSize videoSize = VideoUtil.getVideoSize(videoPath);
String videoSavePath = FileProcessingUtil.getSavePath(videoPath);
try (ProcessWrapper ffmpeg = new DefaultFFMPEGLocator().createExecutor()) {
//读取水印图片
BufferedImage bufferedImage = readAndResizePNGImage(videoSize.getWidth(), videoSize.getHeight(), "static/template/videoWaterMark.png");
File tempImg = FileUtil.createTempFile(".png", true);
ImageIO.write(bufferedImage, "png", tempImg);
long start = System.currentTimeMillis();
LOG.info("开始添加水印....");
ffmpeg.addArgument("-i");
ffmpeg.addArgument(videoPath);
ffmpeg.addArgument("-i");
ffmpeg.addArgument(tempImg.getPath());
ffmpeg.addArgument("-filter_complex");
ffmpeg.addArgument("overlay");
ffmpeg.addArgument(videoSavePath);
ffmpeg.execute();
try (BufferedReader br = new BufferedReader(new InputStreamReader(ffmpeg.getErrorStream()))) {
blockFfmpeg(br);
}
long end = System.currentTimeMillis();
LOG.info("添加水印完成={},耗时{}秒", videoSavePath, (end - start) / 1000);
if (tempImg.delete()) {
LOG.info("删除临时水印图片");
}
} catch (IOException e) {
e.printStackTrace();
throw new CoreException(ErrorCodeEnum.SYS_ERROR, "添加水印失败");
}
return videoSavePath;
}
/**
* 等待命令执行成功,退出
*
* @param br br
* @throws IOException io
*/
private static void blockFfmpeg(BufferedReader br) throws IOException {
String line;
// 该方法阻塞线程,直至合成成功
while ((line = br.readLine()) != null) {
doNothing(line);
}
}
/**
* 打印日志,调试阶段可解开注释,观察执行情况
*
* @param line 每行内容
*/
private static void doNothing(String line) {
// LOG.info(line);
}
}
2.表格文件工具类
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.ReadingOrder;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.Units;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.util.CollectionUtils;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 表格文件工具类
*/
public class ExcelFileUtil {
private static final String XLS_TYPE = "xls";
private static final String XLSX_TYPE = "xlsx";
/**
* 表格文件类型解析
* 取文件的前8个字节来判断
* 用于区分xls和xlsx文件的真实类型,防止用户篡改文件类型
*/
public static String getType(String filePath) {
try (FileInputStream fis = new FileInputStream(filePath)) {
byte[] header = new byte[8];
if (fis.read(header)==8) {
if (isXLSFile(header)) {
return XLS_TYPE;
} else if (isXLSXFile(header)) {
return XLSX_TYPE;
} else {
return "Unknown file format.";
}
}else {
throw new CoreException(ErrorCodeEnum.FILE_READ_FAIL);
}
} catch (IOException e) {
throw new CoreException(ErrorCodeEnum.FILE_READ_FAIL);
}
}
private static boolean isXLSFile(byte[] header) {
return header[0] == (byte) 0xD0 && header[1] == (byte) 0xCF &&
header[2] == (byte) 0x11 && header[3] == (byte) 0xE0 &&
header[4] == (byte) 0xA1 && header[5] == (byte) 0xB1 &&
header[6] == (byte) 0x1A && header[7] == (byte) 0xE1;
}
private static boolean isXLSXFile(byte[] header) {
return header[0] == (byte) 'P' && header[1] == (byte) 'K';
}
/**
* 复制工作簿
* @param source 源文件
* @param destination 目标文件
*/
public static void copySheets(HSSFSheet source, XSSFSheet destination) {
int maxColumnNum = 0;
// 获取全部的合并单元格
List<CellRangeAddress> cellRangeAddressList = source.getMergedRegions();
for (int i = source.getFirstRowNum(); i <= source.getLastRowNum(); i++) {
HSSFRow srcRow = source.getRow(i);
XSSFRow destRow = destination.createRow(i);
if (srcRow != null) {
// 拷贝行
copyRow(destination, srcRow, destRow, cellRangeAddressList);
if (srcRow.getLastCellNum() > maxColumnNum) {
maxColumnNum = srcRow.getLastCellNum();
}
}
}
for (int i = 0; i <= maxColumnNum; i++) {
destination.setColumnWidth(i, source.getColumnWidth(i));
}
// 拷贝图片
copyPicture(source, destination);
}
// 拷贝行
private static void copyRow(XSSFSheet destSheet, HSSFRow srcRow, XSSFRow destRow,
List<CellRangeAddress> cellRangeAddressList) {
// 拷贝行高
destRow.setHeight(srcRow.getHeight());
for (int j = srcRow.getFirstCellNum(); j <= srcRow.getLastCellNum() && j >= 0; j++) {
HSSFCell oldCell = srcRow.getCell(j);
XSSFCell newCell = destRow.getCell(j);
if (oldCell != null) {
if (newCell == null) {
newCell = destRow.createCell(j);
}
// 拷贝单元格
copyCell(oldCell, newCell, destSheet);
// 获取原先的合并单元格
CellRangeAddress mergedRegion = getMergedRegion(cellRangeAddressList, srcRow.getRowNum(),
(short) oldCell.getColumnIndex());
if (mergedRegion != null) {
// 参照创建合并单元格
CellRangeAddress newMergedRegion = new CellRangeAddress(mergedRegion.getFirstRow(),
mergedRegion.getLastRow(), mergedRegion.getFirstColumn(), mergedRegion.getLastColumn());
destSheet.addMergedRegion(newMergedRegion);
}
}
}
}
// 拷贝单元格
private static void copyCell(HSSFCell oldCell, XSSFCell newCell, XSSFSheet destSheet) {
HSSFCellStyle sourceCellStyle = oldCell.getCellStyle();
XSSFCellStyle targetCellStyle = destSheet.getWorkbook().createCellStyle();
if (sourceCellStyle == null) {
sourceCellStyle = oldCell.getSheet().getWorkbook().createCellStyle();
}
targetCellStyle.setFillForegroundColor(sourceCellStyle.getFillForegroundColor());
// 设置对齐方式
targetCellStyle.setAlignment(sourceCellStyle.getAlignment());
targetCellStyle.setVerticalAlignment(sourceCellStyle.getVerticalAlignment());
// 设置字体
XSSFFont xssfFont = destSheet.getWorkbook().createFont();
HSSFFont hssfFont = sourceCellStyle.getFont(oldCell.getSheet().getWorkbook());
copyFont(xssfFont, hssfFont);
targetCellStyle.setFont(xssfFont);
// 文本换行
targetCellStyle.setWrapText(sourceCellStyle.getWrapText());
targetCellStyle.setBorderBottom(sourceCellStyle.getBorderBottom());
targetCellStyle.setBorderLeft(sourceCellStyle.getBorderLeft());
targetCellStyle.setBorderRight(sourceCellStyle.getBorderRight());
targetCellStyle.setBorderTop(sourceCellStyle.getBorderTop());
targetCellStyle.setBottomBorderColor(sourceCellStyle.getBottomBorderColor());
targetCellStyle.setDataFormat(sourceCellStyle.getDataFormat());
targetCellStyle.setFillBackgroundColor(sourceCellStyle.getFillBackgroundColor());
targetCellStyle.setFillPattern(sourceCellStyle.getFillPattern());
targetCellStyle.setHidden(sourceCellStyle.getHidden());
targetCellStyle.setIndention(sourceCellStyle.getIndention());
targetCellStyle.setLeftBorderColor(sourceCellStyle.getLeftBorderColor());
targetCellStyle.setLocked(sourceCellStyle.getLocked());
targetCellStyle.setQuotePrefixed(sourceCellStyle.getQuotePrefixed());
targetCellStyle.setReadingOrder(ReadingOrder.forLong(sourceCellStyle.getReadingOrder()));
targetCellStyle.setRightBorderColor(sourceCellStyle.getRightBorderColor());
targetCellStyle.setRotation(sourceCellStyle.getRotation());
newCell.setCellStyle(targetCellStyle);
switch (oldCell.getCellType()) {
case STRING:
newCell.setCellValue(oldCell.getStringCellValue());
break;
case NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case BLANK:
newCell.setCellType(CellType.BLANK);
break;
case BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case FORMULA:
newCell.setCellFormula(oldCell.getCellFormula());
break;
default:
break;
}
}
// 拷贝字体设置
private static void copyFont(XSSFFont xssfFont, HSSFFont hssfFont) {
xssfFont.setFontName(hssfFont.getFontName());
xssfFont.setBold(hssfFont.getBold());
xssfFont.setFontHeight(hssfFont.getFontHeight());
xssfFont.setCharSet(hssfFont.getCharSet());
xssfFont.setColor(hssfFont.getColor());
xssfFont.setItalic(hssfFont.getItalic());
xssfFont.setUnderline(hssfFont.getUnderline());
xssfFont.setTypeOffset(hssfFont.getTypeOffset());
xssfFont.setStrikeout(hssfFont.getStrikeout());
}
// 根据行列获取合并单元格
public static CellRangeAddress getMergedRegion(List<CellRangeAddress> cellRangeAddressList, int rowNum, short cellNum) {
for (int i = 0; i < cellRangeAddressList.size(); i++) {
CellRangeAddress merged = cellRangeAddressList.get(i);
if (merged.isInRange(rowNum, cellNum)) {
// 已经获取过不再获取
cellRangeAddressList.remove(i);
return merged;
}
}
return null;
}
// 拷贝图片
private static void copyPicture(HSSFSheet source, XSSFSheet destination) {
// 获取sheet中的图片信息
List<Map<String, Object>> mapList = getPicturesFromHSSFSheet(source);
if (CollectionUtils.isEmpty(mapList)) {
return;
}
XSSFDrawing drawing = destination.createDrawingPatriarch();
for (Map<String, Object> pictureMap : mapList) {
HSSFClientAnchor hssfClientAnchor = (HSSFClientAnchor) pictureMap.get("pictureAnchor");
HSSFRow startRow = source.getRow(hssfClientAnchor.getRow1());
float startRowHeight = startRow == null ? source.getDefaultRowHeightInPoints() : startRow.getHeightInPoints();
HSSFRow endRow = source.getRow(hssfClientAnchor.getRow1());
float endRowHeight = endRow == null ? source.getDefaultRowHeightInPoints() : endRow.getHeightInPoints();
// hssf的单元格,每个单元格无论宽高,都被分为 宽 1024个单位 高 256个单位。
// 32.00f 为默认的单元格单位宽度 单元格宽度 / 默认宽度 为像素宽度
XSSFClientAnchor xssfClientAnchor = drawing.createAnchor(
(int) (source.getColumnWidth(hssfClientAnchor.getCol1()) / 32.00f
/ 1024 * hssfClientAnchor.getDx1() * Units.EMU_PER_PIXEL),
(int) (startRowHeight / 256 * hssfClientAnchor.getDy1() * Units.EMU_PER_POINT),
(int) (source.getColumnWidth(hssfClientAnchor.getCol2()) / 32.00f
/ 1024 * hssfClientAnchor.getDx2() * Units.EMU_PER_PIXEL),
(int) (endRowHeight / 256 * hssfClientAnchor.getDy2() * Units.EMU_PER_POINT),
hssfClientAnchor.getCol1(),
hssfClientAnchor.getRow1(),
hssfClientAnchor.getCol2(),
hssfClientAnchor.getRow2());
xssfClientAnchor.setAnchorType(hssfClientAnchor.getAnchorType());
drawing.createPicture(xssfClientAnchor,
destination.getWorkbook().addPicture((byte[]) pictureMap.get("pictureByteArray"),
Integer.parseInt(pictureMap.get("pictureType").toString())));
System.out.println("imageInsert");
}
}
/**
* 获取图片和位置 (xls)
*/
private static List<Map<String, Object>> getPicturesFromHSSFSheet(HSSFSheet sheet) {
List<Map<String, Object>> mapList = new ArrayList<>();
HSSFPatriarch drawingPatriarch = sheet.getDrawingPatriarch();
if (drawingPatriarch == null) {
return null;
}
List<HSSFShape> list = drawingPatriarch.getChildren();
for (HSSFShape shape : list) {
if (shape instanceof HSSFPicture) {
Map<String, Object> map = new HashMap<>();
HSSFPicture picture = (HSSFPicture) shape;
HSSFClientAnchor cAnchor = picture.getClientAnchor();
HSSFPictureData pdata = picture.getPictureData();
map.put("pictureAnchor", cAnchor);
map.put("pictureByteArray", pdata.getData());
map.put("pictureType", pdata.getPictureType());
map.put("pictureSize", picture.getImageDimension());
mapList.add(map);
}
}
return mapList;
}
}
3. PPT工具类
import java.io.FileInputStream;
import java.io.IOException;
public class PowerPointTypeDetectionUtil {
/**
* 取文件的前8个字节来判断
* 用于区分ppt和pptx文件的真实类型,防止用户篡改文件类型
* @param filePath 文件路径
* @return 是否为ppt
*/
public static boolean isPpt(String filePath) {
try (FileInputStream fis = new FileInputStream(filePath)) {
byte[] headerBytes = new byte[8];
fis.read(headerBytes);
return (headerBytes[0] == (byte) 0xD0 &&
headerBytes[1] == (byte) 0xCF &&
headerBytes[2] == (byte) 0x11 &&
headerBytes[3] == (byte) 0xE0 &&
headerBytes[4] == (byte) 0xA1 &&
headerBytes[5] == (byte) 0xB1 &&
headerBytes[6] == (byte) 0x1A &&
headerBytes[7] == (byte) 0xE1);
} catch (IOException e) {
e.printStackTrace();
throw new CoreException(ErrorCodeEnum.FILE_READ_FAIL);
}
}
}
4. 视频工具类
package com.bigdatacd.file.processing.util;
import cn.hutool.core.io.FileUtil;
import com.bigdatacd.data.commons.enums.ErrorCodeEnum;
import com.bigdatacd.data.commons.exception.CoreException;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ws.schild.jave.MultimediaObject;
import ws.schild.jave.info.MultimediaInfo;
import ws.schild.jave.info.VideoSize;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class VideoUtil {
private static final Logger LOG = LoggerFactory.getLogger(VideoUtil.class);
/**
* 读取视频 获取分辨率
*
* @param FileUrl 视频地址
* @return VideoSize
*/
public static VideoSize getVideoSize(String FileUrl) {
File source = new File(FileUrl);
try {
MultimediaObject instance = new MultimediaObject(source);
MultimediaInfo result = instance.getInfo();
return result.getVideo().getSize();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
throw new CoreException(ErrorCodeEnum.FILE_READ_FAIL);
}
}
}