doc/docx水印实现
import com.spire.doc.*;
import com.spire.doc.documents.WatermarkLayout;
import java.awt.*;
import java.io.File;
public class DocWatermarkServiceImpl implements OfficeWatermarkService {
@Override
public void saveWatermark(File file, String watermarkText,String imgPath,Boolean flag) {
//加载测试文档
Document document = new Document();
document.loadFromFile(file.getPath());
document.setWatermark(null);
//这里指定目录下的word文档
//插入文本水印
InsertTextWatermark(document.getSections().get(0), watermarkText,imgPath,flag);
file.delete();
//保存文档
if(file.getPath().endsWith(".docx")) {
document.saveToFile(file.getPath(), FileFormat.Docx);
}else {
document.saveToFile(file.getPath(), FileFormat.Doc);
}
}
//自定义方法指定文本水印字样,并设置成水印
private static void InsertTextWatermark(Section section, String watermarkText,String imgPath,Boolean flag) {
PictureWatermark pictureWatermark = new PictureWatermark();
pictureWatermark.setPicture(imgPath);
TextWatermark txtWatermark = new TextWatermark();
txtWatermark.setText(watermarkText);
txtWatermark.setFontSize(40);
txtWatermark.setColor(Color.red);
txtWatermark.setLayout(WatermarkLayout.Diagonal);
if(flag){
section.getDocument().setWatermark(pictureWatermark);
}else {
section.getDocument().setWatermark(txtWatermark);
}
}
}
xls和xlsx
/**
* xlsx 类型添加水印
*
* @param inputFilePath
* @param text
* @return
*/
public static void excelWaterMarkForXlsx(String inputFilePath, String text, String imgPath, Boolean flag) {
FileInputStream is = null;
FileOutputStream out = null;
XSSFWorkbook workbook = null;
ByteArrayOutputStream os = null;
BufferedImage image = new BufferedImage(200, 400, BufferedImage.TYPE_INT_RGB);
;
try {
//生成水印图片并导出字节流
if (flag) {
File img = new File(imgPath);
BufferedImage bufferedResizedImage = ImageIO.read(img);
Image resizedImage = bufferedResizedImage.getScaledInstance(200, 400, Image.SCALE_SMOOTH);
image = new BufferedImage(200, 400, BufferedImage.TYPE_INT_RGB);
image.getGraphics().drawImage(resizedImage, 0, 0, null);
} else {
image = FontImageUtil.createWatermarkImage(new FontImageUtil.Watermark(true, text, null, null));
}
os = new ByteArrayOutputStream();
ImageIO.write(image, "png", os);
//获取excel工作簿
is = new FileInputStream(inputFilePath);
workbook = new XSSFWorkbook(is);
int pictureIdx = workbook.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
POIXMLDocumentPart poixmlDocumentPart = workbook.getAllPictures().get(pictureIdx);
//获取每个Sheet表并插入水印
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
XSSFSheet sheet1 = workbook.getSheetAt(i);
PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
String relType = XSSFRelation.IMAGES.getRelation();
//add relation from sheet to the picture data
PackageRelationship pr = sheet1.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
//set background picture to sheet
if (sheet1.getCTWorksheet() != null) {
sheet1.getCTWorksheet().unsetPicture();
}
sheet1.getCTWorksheet().addNewPicture().setId(pr.getId());
}
//生成添加水印的excel文件
File f = new File(inputFilePath);
f.delete();
out = new FileOutputStream(inputFilePath);
workbook.write(out);
} catch (Exception e) {
logger.error("excel文件添加水印异常", e);
} finally {
if (is != null) {
try {
is.close();
} catch (Exception e) {
logger.error("excel输入文件关闭异常", e);
}
}
if (out != null) {
try {
out.close();
} catch (Exception e) {
logger.error("excel输出文件关闭异常", e);
}
}
if (workbook != null) {
try {
workbook.close();
} catch (Exception e) {
logger.error("excel工作簿关闭异常", e);
}
}
if (os != null) {
try {
os.close();
} catch (Exception e) {
logger.error("水印图片字节流关闭异常", e);
}
}
}
}
/**
* xls 类型添加水印
*
* @param inputFilePath
* @param text
* @return
*/
public static void excelWaterMarkForXls(String inputFilePath, String text, String imgPath, Boolean flag) {
FileInputStream is = null;
FileOutputStream out = null;
HSSFWorkbook workbook = null;
ByteArrayOutputStream os = null;
BufferedImage image = null;
//水印图片
String tarImgPath = "";
try {
//生成水印图片并导出字节流
if (flag) {
File img = new File(imgPath);
BufferedImage bufferedResizedImage = ImageIO.read(img);
Image resizedImage = bufferedResizedImage.getScaledInstance(200, 400, Image.SCALE_SMOOTH);
image = new BufferedImage(200, 400, BufferedImage.TYPE_INT_RGB);
image.getGraphics().drawImage(resizedImage, 0, 0, null);
tarImgPath = imgPath;
} else {
image = FontImageUtil.createWatermarkImage(new FontImageUtil.Watermark(true, text, null, null));
File f1 = new File(inputFilePath);
tarImgPath = f1.getParent() + File.separator + System.nanoTime() + text + ".png";
}
FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
ImageIO.write(image, "png", outImgStream);
//获取excel工作簿
is = new FileInputStream(inputFilePath);
workbook = new HSSFWorkbook(is);
byte[] data = getBackgroundBitmapData(tarImgPath); //PNG must not have transparency
for (int k = 0; k < workbook.getNumberOfSheets(); k++) {
HSSFSheet sheet1 = workbook.getSheetAt(k);
Field _sheet = HSSFSheet.class.getDeclaredField("_sheet");
_sheet.setAccessible(true);
InternalSheet internalsheet = (InternalSheet) _sheet.get(sheet1);
// get List of RecordBase
Field _records = InternalSheet.class.getDeclaredField("_records");
_records.setAccessible(true);
@SuppressWarnings("unchecked")
List<RecordBase> records = (List<RecordBase>) _records.get(internalsheet);
// do creating BitmapRecord and ContinueRecords from the data in parts of 8220 bytes
BitmapRecord bitmapRecord;
List<ContinueRecord> continueRecords = new ArrayList<>();
int bytes;
if (data.length > 8220) {
bitmapRecord = new BitmapRecord(Arrays.copyOfRange(data, 0, 8220));
bytes = 8220;
while (bytes < data.length) {
if ((bytes + 8220) < data.length) {
continueRecords.add(new ContinueRecord(Arrays.copyOfRange(data, bytes, bytes + 8220)));
bytes += 8220;
} else {
continueRecords.add(new ContinueRecord(Arrays.copyOfRange(data, bytes, data.length)));
break;
}
}
} else {
bitmapRecord = new BitmapRecord(data);
}
int i = 0;
for (RecordBase r : records) {
if (r instanceof org.apache.poi.hssf.record.aggregates.PageSettingsBlock) {
break;
}
i++;
}
records.add(++i, bitmapRecord);
for (ContinueRecord continueRecord : continueRecords) {
records.add(++i, continueRecord);
}
}
//生成添加水印的excel文件
File f = new File(inputFilePath);
f.delete();
String outputFilePath = f.getParent() + File.separator + System.currentTimeMillis() + f.getName();
out = new FileOutputStream(inputFilePath);
logger.info(outputFilePath);
outImgStream.close();
//boolean res = new File(tarImgPath).delete();
workbook.write(out);
} catch (Exception e) {
logger.error("excel文件添加水印异常", e);
} finally {
if (is != null) {
try {
is.close();
} catch (Exception e) {
logger.error("excel输入文件关闭异常", e);
}
}
if (out != null) {
try {
out.close();
} catch (Exception e) {
logger.error("excel输出文件关闭异常", e);
}
}
if (workbook != null) {
try {
workbook.close();
} catch (Exception e) {
logger.error("excel工作簿关闭异常", e);
}
}
if (os != null) {
try {
os.close();
} catch (Exception e) {
logger.error("水印图片字节流关闭异常", e);
}
}
new File(tarImgPath).delete();
}
}
static byte[] getBackgroundBitmapData(String filePath) throws Exception {
//see https://www.openoffice.org/sc/excelfileformat.pdf - BITMAP
// get file byte data in type BufferedImage.TYPE_3BYTE_BGR
FileInputStream fio = new FileInputStream(filePath);
BufferedImage in = ImageIO.read(fio);
BufferedImage image = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
Graphics2D graphics = image.createGraphics();
graphics.drawImage(in, null, 0, 0);
graphics.dispose();
// calculate row size (c)
int rowSize = ((24 * image.getWidth() + 31) / 32) * 4;
ByteArrayOutputStream output = new ByteArrayOutputStream(image.getHeight() * rowSize * 3 + 1024);
// put the record headers into the data
ByteBuffer header = ByteBuffer.allocate(8 + 12);
header.order(ByteOrder.LITTLE_ENDIAN);
// Undocumented XLS stuff
header.putShort((short) 0x09);
header.putShort((short) 0x01);
header.putInt(image.getHeight() * rowSize + 12); // Size of image stream
// BITMAPCOREHEADER (a)
header.putInt(12);
header.putShort((short) image.getWidth());
header.putShort((short) image.getHeight()); // Use -height if writing top-down
header.putShort((short) 1); // planes, always 1
header.putShort((short) 24); // bitcount
output.write(header.array());
// Output rows bottom-up (b)
Raster raster = image.getRaster()
.createChild(0, 0, image.getWidth(), image.getHeight(), 0, 0, new int[]{2, 1, 0}); // Reverse BGR -> RGB (d)
byte[] row = new byte[rowSize]; // padded (c)
for (int i = image.getHeight() - 1; i >= 0; i--) {
row = (byte[]) raster.getDataElements(0, i, image.getWidth(), 1, row);
output.write(row);
}
fio.close();
return output.toByteArray();
}
pdf水印
/**
* PDF添加文字水印
*
* @param srcPdf 上传文件
* @param logoText 水印文字
*/
public static MultipartFile setWaterMarkToPdfByWords(MultipartFile srcPdf, String logoText) {
try {
InputStream inputStream = srcPdf.getInputStream();
PdfDocument pdf = new PdfDocument();
//加载示例文档
pdf.loadFromStream(inputStream);
//true防止中文乱码
PdfTrueTypeFont pdfTrueTypeFont = new PdfTrueTypeFont(new Font("黑体", Font.BOLD, 55), true);
BufferedImage image;
for (int i = 0; i < pdf.getPages().getCount(); i++) {
//当前页
PdfPageBase page = pdf.getPages().get(i);
double width = page.getCanvas().getClientSize().getWidth();
double height = page.getCanvas().getClientSize().getHeight();
//1、当前页进行区域划分,当前页纵向3列,横向3行,共9个区域
Dimension2D dimension2D = new Dimension();
dimension2D.setSize(width, height);
//2、对区域画水印
PdfTilingBrush brush = new PdfTilingBrush(dimension2D);
//透明度
brush.getGraphics().setTransparency(ALPHA);
//旋转角度
brush.getGraphics().rotateTransform(DEGREE);
//设置区域水印位置,垂直水平居中
double offsetX = 0;
double offsetY = brush.getSize().getHeight() / 2;
brush.getGraphics().translateTransform(offsetX, offsetY);
//画水印,居中展示:文本、字体、颜色、x、y、居中展示
brush.getGraphics().drawString(logoText, pdfTrueTypeFont, PdfBrushes.getCadetBlue(), 0, 0, new PdfStringFormat(PdfTextAlignment.Center));
//恢复
brush.getGraphics().restore();
//保存格式
brush.getGraphics().save();
//3、根据当前页大小,创建新画布
Rectangle2D loRect = new Rectangle2D.Float();
loRect.setFrame(new Point2D.Float(0, 0), page.getCanvas().getClientSize());
//4、将新画布和水印画入当前页
page.getCanvas().drawRectangle(brush, loRect);
}
//设置缓存区
pdf.saveToFile(OUT_PATH + srcPdf.getOriginalFilename());
pdf.close();
//读取缓存区的文件
srcPdf = fileToMultipart(OUT_PATH + srcPdf.getOriginalFilename());
} catch (Exception e) {
logger.info("pdf添加水印异常: " + e);
e.printStackTrace();
}
return srcPdf;
}
/**
* pdf图片水印
*
* @param path
* @param imgPath
*/
public static void pdfSavePic(File path,String imgPath){
PdfDocument pdf = new PdfDocument();
//载入PDF文档
pdf.loadFromFile(path.getPath());
//载入图片
PdfImage image = PdfImage.fromFile(imgPath);
//获取图片的宽度和高度用于计算插入水印的初始坐标
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
//循环遍历所有页面以插入水印
for (int i = 0; i < pdf.getPages().getCount(); i++) {
//获取一个页面
PdfPageBase page = pdf.getPages().get(i);
//获取该页面的宽度和高度,用于计算插入水印的初始坐标
float pageWidth = (float) (page.getActualSize().getWidth());
float pageHeight = (float) (page.getActualSize().getHeight());
//设置水印图片的透明度
page.getCanvas().setTransparency(0.3f);
//在页面的中间位置绘制水印图片
page.getCanvas().drawImage(image, pageWidth/2 - imageWidth/2, pageHeight/2 - imageHeight/2, imageWidth, imageHeight);
}
path.delete();
//保存文档
pdf.saveToFile(path.getPath());
}
ppt/pptx实现水印
public static void excelWaterMarkForPPTx(File file, String text, String imgPath, Boolean flag) {
String inputFilePath = file.getPath();
FileInputStream is = null;
FileOutputStream out = null;
XMLSlideShow ppt = null;
ByteArrayOutputStream os = null;
BufferedImage image = null;
try {
// 生成水印图片并导出字节流
if (flag) {
File img = new File(imgPath);
image = ImageIO.read(img);
} else {
image = FontImageUtil.createWatermarkImage(new FontImageUtil.Watermark(true, text, null, null));
}
os = new ByteArrayOutputStream();
ImageIO.write(image, "png", os);
// 获取 PowerPoint 文件
is = new FileInputStream(inputFilePath);
ppt = new XMLSlideShow(is);
List<XSLFPictureData> pictureData = ppt.getPictureData();
List<XSLFPictureData> pictureDataList = new ArrayList<XSLFPictureData>() {{
addAll(pictureData);
}};
int size = pictureData.size();
XSLFPictureData picData = ppt.addPicture(os.toByteArray(), PictureData.PictureType.PNG);
// 遍历每一页并插入水印
for (XSLFSlide slide : ppt.getSlides()) {
if (size != 0) {
if (pictureDataList.contains(picData)) {
return;
} else {
XSLFPictureShape pic = slide.createPicture(picData);
// 设置图片位置和大小
pic.setAnchor(new Rectangle2D.Double(0, 0, picData.getImageDimension().getWidth(), picData.getImageDimension().getHeight()));
//pictureData.removeAll(pictureDataList);
}
} else {
XSLFPictureShape pic = slide.createPicture(picData);
// 设置图片位置和大小
pic.setAnchor(new Rectangle2D.Double(0, 0, picData.getImageDimension().getWidth(), picData.getImageDimension().getHeight()));
}
}
// 生成带水印的 PowerPoint 文件
String tempFilePath = inputFilePath + "temp";
out = new FileOutputStream(tempFilePath);
ppt.write(out);
// 关闭并删除原始文件
ppt.close();
is.close();
out.close();
File originalFile = new File(inputFilePath);
originalFile.delete();
// 重命名临时文件为原始文件
File tempFile = new File(tempFilePath);
tempFile.renameTo(originalFile);
} catch (Exception e) {
logger.error("PowerPoint 文件添加水印异常", e);
} finally {
// 关闭资源
try {
if (is != null) is.close();
} catch (IOException e) {
logger.error("PowerPoint 输入文件关闭异常", e);
}
try {
if (out != null) out.close();
} catch (IOException e) {
logger.error("PowerPoint 输出文件关闭异常", e);
}
try {
if (ppt != null) ppt.close();
} catch (IOException e) {
logger.error("PowerPoint 关闭异常", e);
}
try {
if (os != null) os.close();
} catch (IOException e) {
logger.error("水印图片字节流关闭异常", e);
}
}
}
public static void excelWaterMarkForPPT(File file, String text, String imgPath, Boolean flag) {
String inputFilePath = file.getPath();
FileInputStream is = null;
FileOutputStream out = null;
HSLFSlideShow ppt = null;
ByteArrayOutputStream os = null;
BufferedImage image = null;
try {
if (flag) {
File img = new File(imgPath);
image = ImageIO.read(img);
} else {
image = FontImageUtil.createWatermarkImage(new FontImageUtil.Watermark(true, text, null, null));
}
// 生成水印图片并导出字节流
os = new ByteArrayOutputStream();
ImageIO.write(image, "png", os);
// 获取 PowerPoint 文件
is = new FileInputStream(inputFilePath);
ppt = new HSLFSlideShow(is);
HSLFPictureData picData = ppt.addPicture(os.toByteArray(), PictureData.PictureType.PNG);
// 遍历每一页并插入水印
for (HSLFSlide slide : ppt.getSlides()) {
// 创建图片并设置位置
HSLFPictureShape pic = new HSLFPictureShape(picData);
pic.setAnchor(new Rectangle2D.Double(0, 0, picData.getImageDimension().getWidth(), picData.getImageDimension().getHeight()));
slide.addShape(pic);
}
// 生成带水印的 PowerPoint 文件
String tempFilePath = inputFilePath + "temp";
out = new FileOutputStream(tempFilePath);
ppt.write(out);
// 关闭并删除原始文件
ppt.close();
is.close();
out.close();
File originalFile = new File(inputFilePath);
originalFile.delete();
// 重命名临时文件为原始文件
File tempFile = new File(tempFilePath);
tempFile.renameTo(originalFile);
} catch (Exception e) {
logger.error("PowerPoint 文件添加水印异常", e);
} finally {
// 关闭资源
try {
if (is != null) is.close();
} catch (IOException e) {
logger.error("PowerPoint 输入文件关闭异常", e);
}
try {
if (out != null) out.close();
} catch (IOException e) {
logger.error("PowerPoint 输出文件关闭异常", e);
}
try {
if (ppt != null) ppt.close();
} catch (IOException e) {
logger.error("PowerPoint 关闭异常", e);
}
try {
if (os != null) os.close();
} catch (IOException e) {
logger.error("水印图片字节流关闭异常", e);
}
}
}