背景:oa系统中的一个模块(类似网盘),需要对在线预览,下载的文件动态加上登录人的信息:用户名、账号、时间、组织;考虑如果按照源文件格式下载,水印无法加入并且,用户有可能修改其它用户分享过来的文件,故考虑转曾pdf 进行下载和预览。
一、样例展示:
贴两张水印后预览和下载的效果图:
二、jar包引入
<dependency>
<groupId>com.luhuiguo</groupId>
<artifactId>aspose-words</artifactId>
<version>22.10</version>
</dependency>
<dependency>
<groupId>com.luhuiguo</groupId>
<artifactId>aspose-cells</artifactId>
<version>22.10</version>
</dependency>
<dependency>
<groupId>com.luhuiguo</groupId>
<artifactId>aspose-slides</artifactId>
<version>23.1</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.1</version>
</dependency>
三、jar包引入的方式
1、使用我本地的jar包,下方有下载
链接: https://pan.baidu.com/s/1wnpUCbPPqEDeR22nVGScdw
提取码: 21sv 复制这段内容后打开百度网盘手机App,操作更方便哦
2、在maven 官网找到需要的jar包版本,通过命令的形式打入本地maven库Maven CentralOfficial search by the maintainers of Maven Central Repository.https://central.sonatype.com/
打入本地maven仓库的命令可参考这个博主的:
如何将jar加入自己的maven本地仓库_本地jar上传到私有maven仓库-CSDN博客
四、需要配置一个去除水印的license.xml,放在项目中resource目录下
<?xml version="1.0" encoding="UTF-8" ?>
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
</Data>
<Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>
五、代码展现:
package com.zngk.biz.modular.employeesSpace.utils;
import com.aspose.slides.License;
import com.aspose.slides.Presentation;
import com.aspose.slides.SaveFormat;
import lombok.extern.log4j.Log4j2;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* ppt转pdf工具类
*/
@Log4j2
public class PptConvertPdfUtil {
public static boolean getLicense() {
boolean result = false;
try {
// license.xml应放在.
InputStream is = ExcelConvertPdfUtil.class.getClassLoader().getResourceAsStream("license.xml");
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static void ppt2Pdf(String inPath,String outPath){
// 验证License 去除水印
if (!getLicense()) {
return ;
}
long start = System.currentTimeMillis();
try {
//这里是当inPath地址为http开头的
URL url = new URL(inPath);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStream inputStream = connection.getInputStream();
//这里是当inPath地址为某个盘
//FileInputStream fileInput = new FileInputStream(inPath);
Presentation pres = new Presentation(inputStream);
FileOutputStream out = new FileOutputStream(new File(outPath));
pres.save(out, SaveFormat.Pdf);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
long end =System.currentTimeMillis();
// 转化用时
log.info("pdf转换成功,共耗时:{}" , ((end - start) / 1000.0) + "秒");
}
public static void main(String[] args) {
String inPath = "C:/Users/Asus/Desktop/招聘系统搭建.pptx";
String outPath ="C:/gkzcwebfile/xxx.pdf";
ppt2Pdf(inPath,outPath);
}
}
package com.zngk.biz.modular.employeesSpace.utils;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.Paragraph;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* @author YBug
* @version 1.0
* @date 2024/3/28 10:58
* @Describe
*/
public class TxtConvertPdfUtil {
public static void txt2Pdf(String inputFile,String outputFile){
try {
// 创建文档对象
Document document = new Document();
// 创建PdfWriter对象
PdfWriter.getInstance(document, new FileOutputStream(outputFile));
// 打开文档
document.open();
URL url = new URL(inputFile);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStream inputStream = connection.getInputStream();
// 读取txt文件并写入pdf文件
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
Paragraph paragraph = new Paragraph(line);
document.add(paragraph);
}
// 关闭文档
document.close();
System.out.println("文件转换成功!");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
txt2Pdf("地址", "C:/gkzcwebfile/a.pdf");
}
}
package com.zngk.biz.modular.employeesSpace.utils;
import com.aspose.cells.License;
import com.aspose.cells.PdfSaveOptions;
import com.aspose.cells.Workbook;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
/**
* excel表格转换pdf
*/
@Log4j2
public class ExcelConvertPdfUtil {
public static boolean getLicense() {
boolean result = false;
try {
// license.xml应放在.
InputStream is = ExcelConvertPdfUtil.class.getClassLoader().getResourceAsStream("license.xml");
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* excel 转为pdf 输出。
*
* @param sourceFilePath excel文件
* @param desFilePathd pad 输出文件目录
*/
public static void excel2pdf(String sourceFilePath, String desFilePathd){
// 验证License 若不验证则转化出的pdf文档会有水印产生
if (!getLicense()) {
return;
}
log.info("开始转换excel==start");
FileOutputStream fileOS = null;
long old = System.currentTimeMillis();
try {
URL url = new URL(sourceFilePath);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
BufferedInputStream bis = null;
bis = new BufferedInputStream(connection.getInputStream());
// 原始excel路径
Workbook wb = new Workbook(bis);
fileOS = new FileOutputStream(desFilePathd);
PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
pdfSaveOptions.setOnePagePerSheet(true);
int[] autoDrawSheets={3};
//当excel中对应的sheet页宽度太大时,在PDF中会拆断并分页。此处等比缩放。
autoDraw(wb,autoDrawSheets);
int[] showSheets={0};
//隐藏workbook中不需要的sheet页。
// printSheetPage(wb,showSheets);
wb.save(fileOS, pdfSaveOptions);
fileOS.flush();
long now = System.currentTimeMillis();
log.info("共耗时:{}",((now - old) / 1000.0) );
} catch (Exception e) {
e.printStackTrace();
}finally{
if(fileOS!=null){
try {
fileOS.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 隐藏workbook中不需要的sheet页。
* @param wb
* @param page 显示页的sheet数组
*/
public static void printSheetPage(Workbook wb,int[] page){
for (int i= 1; i < wb.getWorksheets().getCount(); i++) {
wb.getWorksheets().get(i).setVisible(false);
}
if(null==page||page.length==0){
wb.getWorksheets().get(0).setVisible(true);
}else{
for (int i = 0; i < page.length; i++) {
wb.getWorksheets().get(i).setVisible(true);
}
}
}
/**
* 设置打印的sheet 自动拉伸比例
* @param wb
* @param page 自动拉伸的页的sheet数组
*/
public static void autoDraw(Workbook wb,int[] page){
if(null!=page&&page.length>0){
for (int i = 0; i < page.length; i++) {
wb.getWorksheets().get(i).getHorizontalPageBreaks().clear();
wb.getWorksheets().get(i).getVerticalPageBreaks().clear();
}
}
}
public static void main(String[] args) {
String inputExcelPath = "源文件地址";
String outputPdfPath = "C:/gkzcwebfile/xxx.pdf";
excel2pdf(inputExcelPath,outputPdfPath);
}
}
package com.zngk.biz.modular.employeesSpace.utils;
import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* word转换pdf
*/
@Log4j2
public class WordConvertPdfUtil {
public static boolean getLicense() {
boolean result = false;
try {
// license.xml应放在
InputStream is = WordConvertPdfUtil.class.getClassLoader().getResourceAsStream("license.xml");
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF
* @param inPath 源文件路径
* @param outPath 新pdf文件路径
*/
public static void doc2pdf(String inPath, String outPath) {
// 验证License 若不验证则转化出的pdf文档会有水印产生
if (!getLicense()) {
return;
}
log.info("开始转换doc==start");
FileOutputStream os = null;
try {
long old = System.currentTimeMillis();
// 新建一个空白pdf文档
File file = new File(outPath);
os = new FileOutputStream(file);
// Address是将要被转化的word文档
Document doc = new Document(inPath);
// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,
doc.save(os, SaveFormat.PDF);
// EPUB, XPS, SWF 相互转换
long now = System.currentTimeMillis();
// 转化用时
log.info("共耗时:{}",((now - old) / 1000.0) );
} catch (Exception e) {
log.info("转换pdf报错==[{}]",e);
}
finally {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
String inPath = "源文件地址";
String outPath ="C:Users/Asus/Desktop/aa.pdf";
doc2pdf(inPath,outPath);
}
}
六、下方是自定义水印的加入方式,代码有些长,同学可自行吧其中的对象换成自己项目中的
//本地暂存文件的目录
private static String uploadDir = "C:/gkzcwebfile";
private static char fileSeparator = '/';
//上传文件,贴这段代码的目的是因为,文件转pdf 较慢,文件越大转换越慢,我的处理方式是,在上传文件的时候用ThreadUtil.execute去转换,不耽误现有的接口使用
@Override
public String uploadReturnUrlOa(MultipartFile file, String folderName, String fileId) {
return this.storageFileOa(file, false, folderName, fileId);
}
//上传文件的具体实现
private String storageFileOa(MultipartFile file, boolean returnFileId, String folderName, String fileId1) {
BigDecimal a = NumberUtil.div(new BigDecimal(file.getSize()), BigDecimal.valueOf(1024))//本次上传文件的大小
.setScale(0, BigDecimal.ROUND_HALF_UP);
if(isTure(a).equals("1")){
return "1";
}
// 生成id
String fileId = IdWorker.getIdStr();
// 存储桶名称
String bucketName = DevFileMinIoUtil.getDefaultBucketName();;
// 定义存储的url,本地文件返回文件实际路径,其他引擎返回网络地址
String storageUrl = DevFileMinIoUtil.storageFileWithReturnUrl(bucketName, genFileKey(fileId, file), file);
String suffix = ObjectUtil.isNotEmpty(file.getOriginalFilename())?StrUtil.subAfter(file.getOriginalFilename(),
StrUtil.DOT, true):null;
// 将文件信息保存到数据库
DevFile devFile = new DevFile();
// 如果是图片,则压缩生成缩略图
if(ObjectUtil.isNotEmpty(suffix)) {
if(isPic(suffix)) {
try {
devFile.setThumbnail(ImgUtil.toBase64DataUri(ImgUtil.scale(ImgUtil.toImage(file.getBytes()),
100, 100, null), suffix));
} catch (Exception ignored) {
}
}
}
// 设置文件id
devFile.setId(fileId);
// 设置存储引擎类型
devFile.setEngine("MINIO");
devFile.setBucket(bucketName);
String originalFilename = file.getOriginalFilename();
if(originalFilename.contains("/")){
devFile.setName(originalFilename.split("/")[1]);
}else{
devFile.setName(originalFilename);
}
devFile.setSuffix(suffix);
devFile.setSizeKb(Convert.toStr(NumberUtil.div(new BigDecimal(file.getSize()), BigDecimal.valueOf(1024))
.setScale(0, BigDecimal.ROUND_HALF_UP)));
devFile.setSizeInfo(FileUtil.readableFileSize(file.getSize()));
devFile.setObjName(ObjectUtil.isNotEmpty(devFile.getSuffix())?fileId + StrUtil.DOT + devFile.getSuffix():null);
// 存储路径
devFile.setStoragePath(storageUrl);
// 定义下载地址
String downloadUrl;
// MINIO可以直接使用存储地址(公网)作为下载地址
downloadUrl= storageUrl;
devFile.setDownloadPath(devFile.getStoragePath());
devFileOaMapper.insert(devFile);
//注意,需要设置序号,在树形菜单展示会用
OaEmployeeSpaceFiles oaEmployeeSpaceFiles = new OaEmployeeSpaceFiles();
oaEmployeeSpaceFiles.setFileCategory("文件");
oaEmployeeSpaceFiles.setCategory("文件");
oaEmployeeSpaceFiles.setOwner(StpLoginUserUtil.getLoginUser().getAccount());
oaEmployeeSpaceFiles.setOwnerN(StpLoginUserUtil.getLoginUser().getName());
oaEmployeeSpaceFiles.setFileId(fileId);
oaEmployeeSpaceFiles.setParentId(fileId1);
oaEmployeeSpaceFiles.setName(devFile.getName());
//注意 要存kb 和 mb
oaEmployeeSpaceFiles.setSizeInfo(FileUtil.readableFileSize(file.getSize()));
oaEmployeeSpaceFiles.setSizeKb(NumberUtil.div(new BigDecimal(file.getSize()), BigDecimal.valueOf(1024))
.setScale(0, BigDecimal.ROUND_HALF_UP));
oaEmployeeSpaceFiles.setId(IdWorker.getIdStr());
oaEmployeeSpaceFiles.setFileAddress(devFile.getStoragePath());
oaEmployeeSpaceFiles.setCreateUserN(StpLoginUserUtil.getLoginUser().getName());
this.save(oaEmployeeSpaceFiles);
//使用多线转换成pdf文件,为了不耽误现有的接口使用
demo(oaEmployeeSpaceFiles);
// 如果是返回id则返回文件id
if(returnFileId) {
return fileId;
} else {
// 否则返回下载地址
return downloadUrl;
}
}
private void demo(OaEmployeeSpaceFiles oaEmployeeSpaceFiles){
ThreadUtil.execute(() -> {
String tempPdfFilePath = uploadDir + fileSeparator + UUID.randomUUID().toString() + ".pdf";
File file1 = new File(tempPdfFilePath);
//转成pdf
if (oaEmployeeSpaceFiles.getFileAddress().contains(".doc") || oaEmployeeSpaceFiles.getFileAddress().contains(".docx")) {
WordConvertPdfUtil.doc2pdf(oaEmployeeSpaceFiles.getFileAddress(), tempPdfFilePath);
} else if (oaEmployeeSpaceFiles.getFileAddress().contains(".xls") || oaEmployeeSpaceFiles.getFileAddress().contains(".xlxs")) {
ExcelConvertPdfUtil.excel2pdf(oaEmployeeSpaceFiles.getFileAddress(), tempPdfFilePath);
} else if (oaEmployeeSpaceFiles.getFileAddress().contains(".pdf")) {
} else if (oaEmployeeSpaceFiles.getFileAddress().contains(".ppt") || oaEmployeeSpaceFiles.getFileAddress().contains(".pptx")) {
PptConvertPdfUtil.ppt2Pdf(oaEmployeeSpaceFiles.getFileAddress(), tempPdfFilePath);
} else if (oaEmployeeSpaceFiles.getFileAddress().contains(".txt")) {
TxtConvertPdfUtil.txt2Pdf(oaEmployeeSpaceFiles.getFileAddress(), tempPdfFilePath);
}
oaEmployeeSpaceFiles.setFileAddressPdf(tempPdfFilePath);
this.updateById(oaEmployeeSpaceFiles);
});
}
//预览的方法,前端使用的是vue3+pdfjs
@Override
public OaEmployeeSpaceFiles preview(OaEmployeeSpaceFilesPageParam oaEmployeeSpaceFilesPageParam) throws IOException {
//加水印
if (StringUtil.isEmpty(oaEmployeeSpaceFilesPageParam.getFileId())) {
return new OaEmployeeSpaceFiles();
}
QueryWrapper<OaEmployeeSpaceFiles> queryWrapper = new QueryWrapper();
queryWrapper.lambda().eq(OaEmployeeSpaceFiles::getFileId, oaEmployeeSpaceFilesPageParam.getFileId());
List<OaEmployeeSpaceFiles> list = this.list(queryWrapper);
OaEmployeeSpaceFiles oaEmployeeSpaceFiles = list.get(0);
OaEmployeeSpaceFiles file = list.get(0);
OaEmployeeSpaceWatermarkPageParam oaEmployeeSpaceWatermarkPageParam = new OaEmployeeSpaceWatermarkPageParam();
Page<OaEmployeeSpaceWatermark> page = oaEmployeeSpaceWatermarkService.page(oaEmployeeSpaceWatermarkPageParam);
LocalDate localDate = LocalDate.now();
// 水印文本
String watermarkText = "超管/superAdmin/2024-04-08";
if(page.getRecords().size() > 0){
OaEmployeeSpaceWatermark oa = page.getRecords().get(0);
if(oa.getWatermarkContent().indexOf("姓名") != -1){
watermarkText += StpLoginUserUtil.getLoginUser().getName();
}
if(oa.getWatermarkContent().indexOf("工号") != -1){
watermarkText += StpLoginUserUtil.getLoginUser().getAccount();
}
if(oa.getWatermarkContent().indexOf("部门") != -1){
watermarkText += "/" + StpLoginUserUtil.getLoginUser().getOrgName();
}
if(oa.getWatermarkContent().indexOf("时间") != -1){
watermarkText += "/" + localDate;
}
}else{
watermarkText = StpLoginUserUtil.getLoginUser().getName() + StpLoginUserUtil.getLoginUser().getAccount() + "/" + StpLoginUserUtil.getLoginUser().getOrgName() + "/" + localDate;
}
String pdfUrl = oaEmployeeSpaceFilesPageParam.getFileAddress();
//图片也需要上传致服务器返回新的地址,加上水印
if(oaEmployeeSpaceFilesPageParam.getFileType().equals("png") || oaEmployeeSpaceFilesPageParam.getFileType().equals("jpg")){
String waterMarkImage = addWaterMarkImg(watermarkText, oaEmployeeSpaceFiles.getFileAddress(), oaEmployeeSpaceFilesPageParam.getFileType());
byte[] bytes = IoUtil.readBytes(FileUtil.getInputStream(waterMarkImage));
// 存储桶名称
String bucketName = DevFileMinIoUtil.getDefaultBucketName();
// 生成id
String fileId = IdWorker.getIdStr();
// 定义存储的url,本地文件返回文件实际路径,其他引擎返回网络地址
String storageUrl = DevFileMinIoUtil.storageFileWithReturnUrl(bucketName, genFileKeyByte(fileId, oaEmployeeSpaceFilesPageParam.getFileName()), bytes);
System.err.println(storageUrl);
oaEmployeeSpaceFiles.setFileAddress(storageUrl);
}else {
File fileDir = new File(uploadDir);
if (!fileDir.exists()) {
fileDir.mkdirs();
}
String tempPdfFilePath = uploadDir + fileSeparator + UUID.randomUUID().toString()+".pdf";
File file1 = new File(tempPdfFilePath);
if(file.getFileAddressPdf() != null){
tempPdfFilePath = file.getFileAddressPdf();
}else{
if(oaEmployeeSpaceFilesPageParam.getFileType().equals("doc") || oaEmployeeSpaceFilesPageParam.getFileType().equals("docx")){
WordConvertPdfUtil.doc2pdf(oaEmployeeSpaceFilesPageParam.getFileAddress(), tempPdfFilePath);
}else if(oaEmployeeSpaceFilesPageParam.getFileType().equals("xls") || oaEmployeeSpaceFilesPageParam.getFileType().equals("xlxs")){
ExcelConvertPdfUtil.excel2pdf(oaEmployeeSpaceFilesPageParam.getFileAddress(), tempPdfFilePath);
}else if(oaEmployeeSpaceFilesPageParam.getFileType().equals("pdf")){
// 下载PDF文件
try {
downloadPdf1(pdfUrl, file1);
} catch (IOException e) {
e.printStackTrace();
}
}else if(oaEmployeeSpaceFilesPageParam.getFileType().equals("ppt") || oaEmployeeSpaceFilesPageParam.getFileType().equals("pptx")){
PptConvertPdfUtil.ppt2Pdf(oaEmployeeSpaceFilesPageParam.getFileAddress(), tempPdfFilePath);
}else if(oaEmployeeSpaceFilesPageParam.getFileType().equals("txt")){
TxtConvertPdfUtil.txt2Pdf(oaEmployeeSpaceFilesPageParam.getFileAddress(), tempPdfFilePath);
}
file.setFileAddressPdf(tempPdfFilePath);
}
String newtempPdfFilePath = uploadDir + fileSeparator + "NEW"+UUID.randomUUID().toString()+".pdf";
// 添加水印
try {
addWaterMark(tempPdfFilePath, newtempPdfFilePath, watermarkText);
} catch (Exception e) {
e.printStackTrace();
}
File tempFile = new File(newtempPdfFilePath);
//我这边项目使用的是minio 上传文件
byte[] bytes = IoUtil.readBytes(FileUtil.getInputStream(newtempPdfFilePath));
// 存储桶名称
String bucketName = DevFileMinIoUtil.getDefaultBucketName();
// 生成id
String fileId = IdWorker.getIdStr();
// 定义存储的url,本地文件返回文件实际路径,其他引擎返回网络地址
String storageUrl = DevFileMinIoUtil.storageFileWithReturnUrl(bucketName, genFileKeyByte(fileId, oaEmployeeSpaceFilesPageParam.getFileName()), bytes);
System.err.println(storageUrl);
//前端预览的是这个地址:storageUrl,使用的前端技术是pdfjs
oaEmployeeSpaceFiles.setFileAddress(storageUrl);
}
return oaEmployeeSpaceFiles;
}
//pdf文件添加水印的方法
public static void addWaterMark(String inputFile, String outputFile, String waterMarkName) {
PdfReader reader = null;
PdfStamper stamper = null;
try {
reader = new PdfReader(inputFile);
stamper = new PdfStamper(reader, Files.newOutputStream(Paths.get(outputFile)));
//水印字体,放到服务器上对应文件夹下(arial中文不生效)
//BaseFont base = BaseFont.createFont("D:/workspace/springboot/src/main/resources/arial.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
Rectangle pageRect;
PdfGState gs = new PdfGState();
//填充不透明度 为1完全不透明
gs.setFillOpacity(0.05f);
//笔画不透明度, 为1完全不透明
gs.setStrokeOpacity(0.05f);
int total = reader.getNumberOfPages() + 1;
JLabel label = new JLabel();
FontMetrics metrics;
int textH;
int textW;
label.setText(waterMarkName);
metrics = label.getFontMetrics(label.getFont());
textH = metrics.getHeight();
textW = metrics.stringWidth(label.getText());
PdfContentByte under;
int interval = 0;
for (int i = 1; i < total; i++) {
pageRect = reader.getPageSizeWithRotation(i);
//在字体下方加水印
under = stamper.getOverContent(i);
under.beginText();
under.saveState();
under.setGState(gs);
under.setFontAndSize(base, 15);
for (int height = interval + textH; height < pageRect.getHeight(); height = height + textH * 5) {
for (int x = 0; x < 3; x++) {
under.showTextAligned(Element.ALIGN_LEFT, waterMarkName, 50, height - textH, 15);
}
}
for (int height = interval + textH; height < pageRect.getHeight(); height = height + textH * 5) {
for (int x = 0; x < 3; x++) {
under.showTextAligned(Element.ALIGN_LEFT, waterMarkName, 300, height - textH, 15);
}
}
for (int height = interval + textH; height < pageRect.getHeight(); height = height + textH * 5) {
for (int x = 0; x < 3; x++) {
under.showTextAligned(Element.ALIGN_LEFT, waterMarkName, 550, height - textH, 15);
}
}
for (int height = interval + textH; height < pageRect.getHeight(); height = height + textH * 5) {
for (int x = 0; x < 3; x++) {
under.showTextAligned(Element.ALIGN_LEFT, waterMarkName, 850, height - textH, 15);
}
}
under.endText();
}
stamper.close();
reader.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (stamper != null) {
stamper.close();
}
} catch (IOException | com.itextpdf.text.DocumentException e) {
e.printStackTrace();
}
if (reader != null) {
reader.close();
}
}
}
//图片添加水印的方法
private static String addWaterMarkImg(String waterMarkContent, String fileAddress, String fileType) throws IOException {
// 读取原图片信息 得到文件(本地图片)
// File srcImgFile = new File(fileAddress);
// InputStream inputStream = new FileInputStream(srcImgFile);
//读取网络上的图片
URL url = new URL(fileAddress);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStream inputStream = connection.getInputStream();
// 封装为BufferedInputStream,用于流文件类型读取后的重置
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
// 标记读取的文件类型长度
bufferedInputStream.mark(HEADER_SIZE);
// 重置流到开始位置
bufferedInputStream.reset();
BufferedImage targetImg = ImageIO.read(bufferedInputStream);
int height = targetImg.getHeight();
int width = targetImg.getWidth();
BufferedImage waterMarkImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 创建画笔
Graphics2D graphics2D = waterMarkImage.createGraphics();
// 绘制原始图片
graphics2D.drawImage(targetImg, 0, 0, width, height, null);
// 设置水印颜色
graphics2D.setColor(new Color(255, 255, 255, 50));
double scale = 1.0;
if(width < height){
scale = (double) width / height;
}
int fontSize = (int) Math.ceil((double) (height / 45) * scale);
// 设置字体 画笔字体样式为微软雅黑,加粗,文字大小按比例给
graphics2D.setFont(new Font("微软雅黑", Font.BOLD, fontSize));
// 水印旋转度
graphics2D.rotate(Math.toRadians(-25), (double) width / 2, (double) height / 2);
int x = -width * 3;
int y;
// 计算水印文字的宽度
FontMetrics fontMetrics = graphics2D.getFontMetrics();
int watermarkWidth = fontMetrics.stringWidth(waterMarkContent);
// 水印横向间隔
int positionWidth = (int)(width * 0.15);
// 水印竖向间隔
int positionHeight = (int)(height * 0.15);
while (x < width * 3) {
y = -height * 3;
while (y < height * 3) {
graphics2D.drawString(waterMarkContent, x, y);
y += fontSize + positionWidth;
}
x += watermarkWidth + positionHeight;
}
graphics2D.dispose();
String tarImgPath = uploadDir + fileSeparator + UUID.randomUUID().toString()+"." + fileType;
FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
ImageIO.write(waterMarkImage, fileType, outImgStream);
outImgStream.flush();
outImgStream.close();
return tarImgPath;
}
//这里是下载文件的具体实现
@Override
public void download(OaEmployeeSpaceFilesPageParam oaEmployeeSpaceFilesPageParam,HttpServletResponse response) throws IOException {
if (StringUtil.isEmpty(oaEmployeeSpaceFilesPageParam.getFileId())) {
return;
}
OaEmployeeSpaceWatermarkPageParam oaEmployeeSpaceWatermarkPageParam = new OaEmployeeSpaceWatermarkPageParam();
Page<OaEmployeeSpaceWatermark> page = oaEmployeeSpaceWatermarkService.page(oaEmployeeSpaceWatermarkPageParam);
LocalDate localDate = LocalDate.now();
// 水印文本
String watermarkText = "超管/superAdmin/2024-04-08";
// if(page.getRecords().size() > 0){
// OaEmployeeSpaceWatermark oa = page.getRecords().get(0);
// if(oa.getWatermarkContent().indexOf("姓名") != -1){
// watermarkText += StpLoginUserUtil.getLoginUser().getName();
// }
//
// if(oa.getWatermarkContent().indexOf("工号") != -1){
// watermarkText += StpLoginUserUtil.getLoginUser().getAccount();
// }
//
// if(oa.getWatermarkContent().indexOf("部门") != -1){
// watermarkText += "/" + StpLoginUserUtil.getLoginUser().getOrgName();
// }
//
// if(oa.getWatermarkContent().indexOf("时间") != -1){
// watermarkText += "/" + localDate;
// }
// }else{
// watermarkText = StpLoginUserUtil.getLoginUser().getName() + StpLoginUserUtil.getLoginUser().getAccount() + "/" + StpLoginUserUtil.getLoginUser().getOrgName() + "/" + localDate;
// }
//源文件地址
String pdfUrl = oaEmployeeSpaceFilesPageParam.getFileAddress();
if(oaEmployeeSpaceFilesPageParam.getFileType().equals("png") || oaEmployeeSpaceFilesPageParam.getFileType().equals("jpg")){
String waterMarkImage = addWaterMarkImg(watermarkText, oaEmployeeSpaceFilesPageParam.getFileAddress(), oaEmployeeSpaceFilesPageParam.getFileType());
//这个接口返回给前端的是给文件流,前端有的对应的下载文件代码,在本次代码的末尾,可进行参考
CommonDownloadUtil.download(oaEmployeeSpaceFilesPageParam.getFileName(), IoUtil.readBytes(FileUtil.getInputStream(waterMarkImage)), response);
}else {
File fileDir = new File(uploadDir);
if (!fileDir.exists()) {
fileDir.mkdirs();
}
String tempPdfFilePath = uploadDir + fileSeparator + UUID.randomUUID().toString()+".pdf";
File file1 = new File(tempPdfFilePath);
if(file.getFileAddressPdf() != null){
tempPdfFilePath = file.getFileAddressPdf();
}else{
if(oaEmployeeSpaceFilesPageParam.getFileType().equals("doc") || oaEmployeeSpaceFilesPageParam.getFileType().equals("docx")){
WordConvertPdfUtil.doc2pdf(oaEmployeeSpaceFilesPageParam.getFileAddress(), tempPdfFilePath);
}else if(oaEmployeeSpaceFilesPageParam.getFileType().equals("xls") || oaEmployeeSpaceFilesPageParam.getFileType().equals("xlxs")){
ExcelConvertPdfUtil.excel2pdf(oaEmployeeSpaceFilesPageParam.getFileAddress(), tempPdfFilePath);
}else if(oaEmployeeSpaceFilesPageParam.getFileType().equals("pdf")){
// 下载PDF文件
try {
downloadPdf1(pdfUrl, file1);
} catch (IOException e) {
e.printStackTrace();
}
}else if(oaEmployeeSpaceFilesPageParam.getFileType().equals("ppt") || oaEmployeeSpaceFilesPageParam.getFileType().equals("pptx")){
PptConvertPdfUtil.ppt2Pdf(oaEmployeeSpaceFilesPageParam.getFileAddress(), tempPdfFilePath);
}else if(oaEmployeeSpaceFilesPageParam.getFileType().equals("txt")){
TxtConvertPdfUtil.txt2Pdf(oaEmployeeSpaceFilesPageParam.getFileAddress(), tempPdfFilePath);
}
//这里读取的是上传的时候转码之后的pdf文件存放地址
file.setFileAddressPdf(tempPdfFilePath);
}
this.updateById(file);
String newtempPdfFilePath = uploadDir + fileSeparator + "NEW"+UUID.randomUUID().toString()+".pdf";
// 添加水印
try {
addWaterMark(tempPdfFilePath, newtempPdfFilePath, watermarkText);
} catch (Exception e) {
e.printStackTrace();
}
File tempFile = new File(newtempPdfFilePath);
CommonDownloadUtil.download(oaEmployeeSpaceFilesPageParam.getFileName(), IoUtil.readBytes(FileUtil.getInputStream(tempFile)), response);
}
}
//下载pdf文件
public static void downloadPdf1(String pdfUrl, File file) throws IOException {
URL url = new URL(pdfUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStream inputStream = connection.getInputStream();
FileOutputStream outputStream = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
}
//匹配文件格式
private static boolean isPic(String fileSuffix) {
fileSuffix = fileSuffix.toLowerCase();
return ImgUtil.IMAGE_TYPE_GIF.equals(fileSuffix)
|| ImgUtil.IMAGE_TYPE_JPG.equals(fileSuffix)
|| ImgUtil.IMAGE_TYPE_JPEG.equals(fileSuffix)
|| ImgUtil.IMAGE_TYPE_BMP.equals(fileSuffix)
|| ImgUtil.IMAGE_TYPE_PNG.equals(fileSuffix)
|| ImgUtil.IMAGE_TYPE_PSD.equals(fileSuffix);
}
/**
* 生成文件的key,格式如 2021/10/11/1377109572375810050.docx
*
* @author xuyuxiang
* @date 2022/4/22 15:58
**/
public String genFileKey(String fileId, MultipartFile file) {
// 获取文件原始名称
String originalFileName = file.getOriginalFilename();
// 获取文件后缀
String fileSuffix = FileUtil.getSuffix(originalFileName);
// 生成文件的对象名称,格式如:1377109572375810050.docx
String fileObjectName = fileId + StrUtil.DOT + fileSuffix;
// 获取日期文件夹,格式如,2021/10/11/
String dateFolderPath = DateUtil.thisYear() + StrUtil.SLASH +
(DateUtil.thisMonth() + 1) + StrUtil.SLASH +
DateUtil.thisDayOfMonth() + StrUtil.SLASH;
// 返回
return dateFolderPath + fileObjectName;
}
public String genFileKeyByte(String fileId, String fileName) {
// 获取文件原始名称
String originalFileName = fileName;
// 获取文件后缀
String fileSuffix = FileUtil.getSuffix(originalFileName);
// 生成文件的对象名称,格式如:1377109572375810050.docx
String fileObjectName = fileId + StrUtil.DOT + fileSuffix;
// 获取日期文件夹,格式如,2021/10/11/
String dateFolderPath = DateUtil.thisYear() + StrUtil.SLASH +
(DateUtil.thisMonth() + 1) + StrUtil.SLASH +
DateUtil.thisDayOfMonth() + StrUtil.SLASH;
// 返回
return dateFolderPath + fileObjectName;
}
//以下是前端代码
const urlToBold = (res, fileType) => {
// 将链接地址字符内容转变成blob地址
const aLink = document.createElement('a')
let href = window.URL.createObjectURL(res.data)
let name = currentFile.value.name
if(fileType == 'png' || fileType == 'jpg'){
name=name.substr(0,name.lastIndexOf('.')) + '.' + fileType
}else{
name=name.substr(0,name.lastIndexOf('.')) + '.pdf'
}
aLink.download = name
aLink.href = href
document.body.appendChild(aLink)
aLink.click()
document.body.removeChild(aLink) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉blob对象
}
描述:以上内容是记录自己工作中遇到的文件转pdf,加上水印的需求,也希望能帮助到有需要的同学