给文件加水印(Word、PDF)并压缩
word分为doc文件和docx文件。HWPFDocument是用来操作doc文件的;XWPFDocument 是用来操作docx的。
由于当时无法创建HWPFDocument 对象,所以如果是doc文件的话会转换成docx然后再加水印。
@ApiOperation(value = "下载附件", notes = "下载附件")
@PostMapping("/download")
@ResponseBody
public ResponseEntity<FileSystemResource> download(@RequestBody NonLitigationVO nonLitigationVO, HttpServletResponse response) throws IOException, XmlException {
if (nonLitigationVO!=null&&nonLitigationVO.getAnnexId()!=null){
String annexId = nonLitigationVO.getAnnexId();
String[] split = annexId.split(",");
List<Attachment> attachments = attachmentMapper.selectByAttachmentIds(split);
if (attachments!=null&&attachments.size()>0){
//设置压缩路径f
String f =attachmentConfig.getPath()+"FS"+DateUtils.dateTimeNow("yyyyMMddHHmmss")+RandomUtil.randomNumbers(4)+"/";//DB adress
File file = new File(f);
//创建文件夹
boolean mkdirs = file.mkdirs();
for (Attachment attachment : attachments) {
// 给文件加水印
WatermarkUtil.addWatermark(new File(attachmentConfig.getPath() + attachment.getAttachmentAddress()),f); }
int length = file.listFiles().length;
//打包
File zip = ZipUtil.zip(f);
//导出
return export(zip);
}}
return null;
}
工具类
package com.boot.reservation.util;
import com.aspose.words.SaveFormat;
import org.apache.poi.poifs.filesystem.*;
import org.apache.poi.ss.usermodel.*;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Element;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlToken;
import org.springframework.util.FileCopyUtils;
import java.io.*;
import java.util.List;
import java.util.regex.Pattern;
import static com.boot.reservation.util.ExcelToPDFUtils.getLicense;
public class WatermarkUtil {
private static final String WATERMARK = "泰裤辣!!!!";
public static void addWatermark(File file,String folder) throws IOException, XmlException {
String extension = getFileExtension(file);
switch (extension) {
case "doc":
handlerByDocFile(file,folder);
break;
case "docx":
waterMark2Word(file,folder);
break;
case "pdf":
addWatermarkToPDF(file,folder);
break;
default:
System.out.println("Unsupported file format");
}
}
private static String getFileExtension(File file) {
String name = file.getName();
int lastIndexOf = name.lastIndexOf(".");
if (lastIndexOf == -1) {
return "";
}
return name.substring(lastIndexOf + 1);
}
public static void waterMark2Word(File file,String folder) throws IOException {
// if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
// return;
// }
String path =file.getPath();
String name =file.getName();
String modelPath = folder+name;//设置需要加水印的文件路径
//输入的docx文档
try{
InputStream in = new FileInputStream(new File(path));
XWPFDocument doc= new XWPFDocument(in);
XWPFParagraph paragraph = doc.createParagraph();//创建文本段落
// XWPFRun run=paragraph.createRun();//创建run元素
// run.setText("The Body:");//可以给run元素里写正文内容
XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy();//获取页面页脚
if (headerFooterPolicy == null) {
headerFooterPolicy = doc.createHeaderFooterPolicy();//如果没有页眉页脚则创建
}
headerFooterPolicy.createWatermark(WATERMARK);//设置水印显示的内容
XWPFHeader header = headerFooterPolicy.getHeader(XWPFHeaderFooterPolicy.DEFAULT);
paragraph = header.getParagraphArray(0);
org.apache.xmlbeans.XmlObject[] xmlobjects = paragraph.getCTP().getRArray(0).getPictArray(0).selectChildren(
new javax.xml.namespace.QName("urn:schemas-microsoft-com:vml", "shape"));
if (xmlobjects.length > 0) {
com.microsoft.schemas.vml.CTShape ctshape = (com.microsoft.schemas.vml.CTShape)xmlobjects[0];
ctshape.setFillcolor("#d8d8d8");//设置水印的颜色
ctshape.setStyle(ctshape.getStyle() + ";rotation:45");//设置水印的样式 获取默认样式和旋315度
ctshape.setStyle(getWaterMarkStyle(ctshape.getStyle(),100) + ";rotation:315");//设置自定义水印的样式,setStyle()方法中需传入样式字符串
}
FileOutputStream fileOutputStream = new FileOutputStream(modelPath);
doc.write(fileOutputStream);
doc.close();
}catch (Exception e){
handlerByDocFile(file,folder);
}
}
/**
* @param
* @param
*/
//pdf格式 动态 xy坐标轴 斜体居中
public static void addWatermarkToPDF(File file,String folder) {
try {
String path = file.getPath();
String name = file.getName();
String modelPath = folder+name;
path = java.net.URLDecoder.decode(path, "utf-8");
PdfReader reader = new PdfReader(path);
FileOutputStream fileOutputStream = new FileOutputStream(modelPath);
PdfStamper stamper = new PdfStamper(reader,fileOutputStream);
//这里的字体设置比较关键,这个设置是支持中文的写法
BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);// 使用系统字体
int total = reader.getNumberOfPages() + 1;
PdfContentByte under;
Rectangle pageRect = null;
for (int i = 1; i < total; i++) {
pageRect = stamper.getReader().getPageSizeWithRotation(i);
// 计算水印X,Y坐标
float x = pageRect.getWidth() / 2;
float y = pageRect.getHeight() / 2;
// 获得PDF最顶层
under = stamper.getOverContent(i);
under.saveState();
// set Transparency
PdfGState gs = new PdfGState();
// 设置透明度为0.8
gs.setFillOpacity(0.6f);
under.setGState(gs);
under.beginText();
under.setFontAndSize(base, 100);
under.setColorFill(BaseColor.GRAY);
// 水印文字成45度角倾斜
under.showTextAligned(Element.ALIGN_CENTER, WATERMARK, x, y, 65);
// 添加水印文字
under.endText();
under.setLineWidth(1f);
under.stroke();
under.restoreState();
}
stamper.close();
stamper.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 将水印中的文字替换成传进来的字符串
* @param graph 要替换的段落
* @param waterMarkValue 水印文字
* @throws IOException
* @throws XmlException
*/
public static void replaceWaterMark(XWPFParagraph graph,String waterMarkValue) throws IOException, XmlException {
String paraText = graph.getCTP().xmlText();
if(paraText.contains("id=\"PowerPlusWaterMarkObject")){//<v:shape id=\"PowerPlusWaterMarkObject
String beginStr = "string=\"";
int begin = paraText.indexOf(beginStr) + beginStr.length();
int end = paraText.indexOf("\"", begin);
String oldWaterMarkText = paraText.substring(begin, end);
String newText = paraText.replace("string=\""+ oldWaterMarkText +"\"",
"string=\"" + waterMarkValue + "\"");
XmlToken token = XmlToken.Factory.parse(newText);
graph.getCTP().set(token);
}
}
/**
* 设置水印格式
* word
*
* @param styleStr
* @param height
* @return
*/
public static String getWaterMarkStyle(String styleStr, double height) {
Pattern p = Pattern.compile(";");
String[] strs = p.split(styleStr);
for (String str : strs) {
if (str.startsWith("height:")) {
String heightStr = "height:" + height + "pt";
styleStr = styleStr.replace(str, heightStr);
break;
}
}
return styleStr;
}
public static void handlerByDocFile(File file, String folder) throws IOException {
ByteArrayToFile(convertDocIs2DocxIs( new FileInputStream(new File(file.getPath()))),"cv"+file.getName());
waterMark2Word(new File("cv"+file.getName()),folder);
}
public static void ByteArrayToFile(byte[] data,String newFileNmae) {
File file = new File(newFileNmae);
//选择流
FileOutputStream fos = null;
ByteArrayInputStream bais = null;
try {
bais = new ByteArrayInputStream(data);
fos = new FileOutputStream(file);
int temp;
byte[] bt = new byte[1024*10];
while((temp = bais.read(bt))!= -1) {
fos.write(bt,0,temp);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//关流
try {
if(null != fos) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 将doc输入流转换为docx输入流
private static byte[] convertDocIs2DocxIs(InputStream docInputStream) throws IOException {
byte[] docBytes = FileCopyUtils.copyToByteArray(docInputStream);
byte[] docxBytes = convertDocStream2docxStream(docBytes);
return docxBytes;
}
// 将doc字节数组转换为docx字节数组
private static byte[] convertDocStream2docxStream(byte[] arrays) {
byte[] docxBytes = new byte[1];
if (arrays != null && arrays.length > 0) {
try (
ByteArrayOutputStream os = new ByteArrayOutputStream();
InputStream sbs = new ByteArrayInputStream(arrays);
) {
// HWPFDocument hwpfDocument = new HWPFDocument(sbs);
// hwpfDocument.delete(1,70);
com.aspose.words.Document doc = new com.aspose.words.Document(sbs);
doc.save(os, SaveFormat.DOCX);
docxBytes = os.toByteArray();
} catch (Exception e) {
System.out.println("出错啦");
}
}
return docxBytes;
}
}
导出方法
public ResponseEntity<FileSystemResource> export(File file) {
if (file == null) {
return null;
}
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Content-Disposition", "attachment; filename=" + file.getName());
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
headers.add("Last-Modified", new Date().toString());
headers.add("ETag", String.valueOf(System.currentTimeMillis()));
// headers.add("url",attachmentConfig.getIp()+attachmentConfig.getPort()+file.getPath());
return ResponseEntity.ok().headers(headers).contentLength(file.length()).contentType(MediaType.parseMediaType("application/octet-stream")).body(new FileSystemResource(file));
}