PDF文件加水印

该文详细介绍了如何在Linux系统中安装中文字体,然后利用Java编程实现PDF文件添加水印、PDF转图片以及图片转PDF的功能。主要涉及iTextPDF和ApachePDFBox两个库,包括字体设置、水印添加、PDF操作等步骤。
摘要由CSDN通过智能技术生成

一、设计思路

二、准备工作

1、linux安装中文字体文件

1)准备字体文件

找到windows系统的字体文件夹:C:\Windows\Fonts

可以看到有很多字体文件,不需要全部使用,只需要中文的即可,根据需要选取

2)linux字体文件安装

cd /usr/share/fonts/ #进入字体目录
mkdir chinese #将windows系统中的字体文件上传到linux系统该文件夹中
chmod 755 /usr/share/fonts/chinese/* #更改字体权限
cd /usr/share/fonts/chinese #进入字体目录
mkfontscale #(若提示“mkfontscale command not found",则运行 yum install mkfontscale)
mkfontdir #(若提示“Couldn't determine full name for xxx.fon,则删除与之对应的文件)
fc-cache

2、添加maven依赖

<!-- PDF添加水印依赖 -->
<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>itextpdf</artifactId>
  <version>5.5.5</version>
</dependency>
<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>itext-asian</artifactId>
  <version>5.2.0</version>
</dependency>
<!-- PDF操作工具包 -->
<dependency>
  <groupId>org.apache.pdfbox</groupId>
  <artifactId>pdfbox-app</artifactId>
  <version>2.0.16</version>
</dependency>

三、开发流程

1、获取原始pdf文件

方法:File file = new File("文件路径");

2、获取原始pdf文件byte数组

方法:handleReadData

3、原始pdf文件添加水印

方法:pdfAddWaterMark

4、添加水印的pdf文件转图片

方法:pdfToImage,默认转为png格式,可手动修改(代码189行),返回pdf图片集合

5、创建空白pdf文件

方法:createBlankPdf

6、pdf图片集合转为新的pdf

方法:fillImg2Pdf,将pdf图片集合添加到创建的空白pdf文档内

7、删除文件(可选)

方法:delFolder(删除文件夹)、delAllFile(删除指定文件夹下所有文件)

四、完整代码

package com.hylink.utils;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.*;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.PDFRenderer;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;

public class PDFUtil {

    //服务器字体文件路径
//    public static final String fontsPath = "/static/fonts/STCAIYUN.TTF";
    public static final String fontsPath = "C:\\Windows\\Fonts\\STCAIYUN.TTF";

    public static void main(String[] args) throws Exception {
        File file = new File("C:\\Users\\Administrator\\Desktop\\demo\\耕地承包申请书.pdf");
        byte[] bytes = handleReadData(file);
        String fileName = UUID.randomUUID() + ".pdf";
        String saveFilePath = "C:\\Users\\Administrator\\Desktop\\demo";

        pdfAddWaterMark(bytes, "仅用于办理土地承包申请", fileName, saveFilePath, 2);

//        List<File> files = pdfToImage("C:\\Users\\Administrator\\Desktop\\demo\\690146b1-f169-4d9c-906f-695aa32b556c.pdf", "C:\\Users\\Administrator\\Desktop\\demo", 144);
//        File targetFile = new File("C:\\Users\\Administrator\\Desktop\\demo\\1.pdf");
//        createBlankPdf(targetFile, files.size());
//        fillImg2Pdf(targetFile, files);
    }

    public static byte[] handleReadData(File file) {
        try {
            FileInputStream in = new FileInputStream(file);
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            byte[] tmpBuffer = new byte[(2 << 9) * 1];
            int count;
            while ((count = in.read(tmpBuffer)) != -1) {
                byteOut.write(tmpBuffer, 0, count);
                tmpBuffer = new byte[(2 << 9) * 1];
            }
            in.close();
            return byteOut.toByteArray();

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * PDF文件转PNG图片,全部页数
     *
     * @param PdfFilePath  pdf完整路径
     * @param dstImgFolder 图片存放的文件夹
     * @param dpi          dpi越大转换后越清晰,相对转换速度越慢
     * @return 返回转换后图片集合list
     */
    public static List<File> pdfToImage(String PdfFilePath, String dstImgFolder, int dpi) {
        UUID uuid = UUID.randomUUID();
        String uuId = uuid.toString();
        System.out.println(uuId);
        File file = new File(PdfFilePath);
        //定义集合保存返回图片数据
        List<File> fileList = new ArrayList<File>();
        @SuppressWarnings("resource")//抑制警告
        PDDocument pdDocument = new PDDocument();
        try {
            //String imagePDFName = file.getName().substring(0, dot); // 获取图片文件名
            String imgFolderPath = null;
            if (dstImgFolder.equals("")) {
                imgFolderPath = dstImgFolder + File.separator + uuId;// 获取图片存放的文件夹路径
            } else {
                imgFolderPath = dstImgFolder + File.separator + uuId;
            }
            if (createDirectory(imgFolderPath)) {
                pdDocument = PDDocument.load(file);
                PDFRenderer renderer = new PDFRenderer(pdDocument);
                /* dpi越大转换后越清晰,相对转换速度越慢 */
                PdfReader reader = new PdfReader(PdfFilePath);
                int pages = reader.getNumberOfPages();
                System.out.println("pdf总共多少页-----" + pages);
                StringBuffer imgFilePath = null;
                for (int i = 0; i < pages; i++) {
                    String imgFilePathPrefix = imgFolderPath + File.separator + "pdf";
                    System.out.println("imgFilePathPrefix=====" + imgFilePathPrefix);
                    imgFilePath = new StringBuffer();
                    imgFilePath.append(imgFilePathPrefix);
                    imgFilePath.append("-");
                    imgFilePath.append(i);
                    imgFilePath.append(".png");
                    File dstFile = new File(imgFilePath.toString());
                    BufferedImage image = renderer.renderImageWithDPI(i, dpi);
                    ImageIO.write(image, "png", dstFile);
                    fileList.add(dstFile);
                }
                System.out.println("PDF文档转PNG图片成功!");
                return fileList;
            } else {
                System.out.println("PDF文档转PNG图片失败:" + "创建" + imgFolderPath + "失败");
                return null;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * pdf 加水印
     *
     * @param byes         待加水印文件字节数组
     * @param waterMarkStr 水印字符串
     * @param fileName     最终文件名称
     * @param saveFilePath 保存地址
     * @param number       每页水印条数
     */
    public static void pdfAddWaterMark(byte[] byes, String waterMarkStr, String fileName, String saveFilePath, int number) {

        String courseFile = "";
        try {
            //生成临时文件 , 读取完删除
            File directory = new File(saveFilePath);
            courseFile = directory.getCanonicalPath() + "/";
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 待加水印的文件
        PdfReader reader = null;
        PdfStamper stamper = null;
        FileOutputStream os = null;
        try {
            reader = new PdfReader(byes);
            // 加完水印的文件
            os = new FileOutputStream(courseFile + fileName);
            stamper = new PdfStamper(reader, os);

            int total = reader.getNumberOfPages() + 1;
            PdfContentByte content;
            // 字体库字体
//            BaseFont basefont = BaseFont.createFont(fontsPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            //这里的字体设置比较关键,这个设置是支持中文的写法 使用系统字体
            BaseFont basefont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);

            PdfContentByte under;
            com.itextpdf.text.Rectangle pageRect = null;

            // 循环对每页插入水印
            for (int i = 1; i < total; i++) {
                pageRect = stamper.getReader().getPageSizeWithRotation(i);
                // 计算水印X,Y坐标
                float x = (float) (pageRect.getWidth() / 1.98);
                float y = (float) (pageRect.getHeight() / 2.8);
                // 获得PDF最顶层
                under = stamper.getOverContent(i);
                under.saveState();
                under.restoreState();
                under.beginText();
                // set Transparency
                PdfGState gs = new PdfGState();
                // 设置透明度为0.2
                gs.setFillOpacity(0.3f);
                under.setGState(gs);
                // 水印字体和大小
                under.setFontAndSize(basefont, pageRect.getHeight() / 17);
                // 水印颜色
                under.setColorFill(BaseColor.RED);
                // 水印文字成45度角倾斜
                for (int j = 0; j < number; j++) {
                    under.showTextAligned(Element.ALIGN_CENTER, waterMarkStr, x, y * (j + 1), 45);
                }
                // 添加水印文字
                under.endText();
                under.setLineWidth(1f);
                under.stroke();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } finally {
            try {
                stamper.close();
                if (os != null) {
                    os.close();
                }
                if (reader != null) {
                    reader.close();
                }
            } catch (DocumentException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //创建文件夹
    private static boolean createDirectory(String folder) {
        File dir = new File(folder);
        if (dir.exists()) {
            return true;
        } else {
            return dir.mkdirs();
        }
    }

    //删除文件夹
    //param folderPath 文件夹完整绝对路径
    public static void delFolder(String folderPath) {
        try {
            delAllFile(folderPath); //删除完里面所有内容
            String filePath = folderPath;
            filePath = filePath;
            File myFilePath = new File(filePath);
            myFilePath.delete(); //删除空文件夹
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //删除指定文件夹下所有文件
    //param path 文件夹完整绝对路径
    public static boolean delAllFile(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return flag;
        }
        if (!file.isDirectory()) {
            return flag;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();

            }
            if (temp.isDirectory()) {
                delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件
                delFolder(path + "/" + tempList[i]);//再删除空文件夹
                flag = true;
            }
        }
        return flag;
    }

    /**
     * 创建空白PDF文档
     *
     * @param pageNum
     */
    public static void createBlankPdf(File targetFile, int pageNum) {
        // 创建文档
        PDDocument pdDocument = new PDDocument();
        // 设置文档属性
        createMainInformation(pdDocument);
        for (int i = 0; i < pageNum; i++) {
            // 创建页码
            PDPage blankPage = new PDPage();
            // 添加到文档
            pdDocument.addPage(blankPage);
        }
        try {
            // 保存文档
            pdDocument.save(targetFile);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭文档
                pdDocument.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 设置文档属性
     *
     * @param pdDocument
     */
    public static void createMainInformation(PDDocument pdDocument) {
        PDDocumentInformation pdd = pdDocument.getDocumentInformation();
        pdd.setAuthor("章三");
        pdd.setTitle("图片转换PDF");
        pdd.setCreator("PDF Examples");
        pdd.setSubject("主题哦");
        Calendar date = new GregorianCalendar();
        date.set(2019, 11, 6);
        pdd.setCreationDate(date);
        date.set(2019, 11, 7);
        pdd.setModificationDate(date);
        pdd.setKeywords("hi, my pdf!");
    }

    /**
     * 填充图片到PDF文件
     */
    public static void fillImg2Pdf(File targetFile, List<File> imgFileList) {
        // 加载现有文档
        PDDocument doc = null;
        try {
            doc = PDDocument.load(targetFile);
            for (int i = 0; i < imgFileList.size(); i++) {
                File imgFile = imgFileList.get(i);
                // 获取文档页面
                PDPage page = doc.getPage(i);
                PDImageXObject pdImage = PDImageXObject.createFromFile(imgFile.getPath(), doc);
                PDPageContentStream contents = new PDPageContentStream(doc, page);
                Map<String, Float> sizeMap = getSize(imgFile, page, 30, 30);
                contents.drawImage(pdImage, sizeMap.get("x"), sizeMap.get("y"), sizeMap.get("width"), sizeMap.get("height"));
                contents.close();
            }
            doc.save(targetFile);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (doc != null) {
                try {
                    doc.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * @param imgFile 图片文件
     * @param page    PDF页
     * @param paddW   横向内边距
     * @param paddH   纵向内边距
     * @return
     */
    private static Map<String, Float> getSize(File imgFile, PDPage page, float paddW, float paddH) {
        Map<String, Float> map = new HashMap<String, Float>();
        BufferedImage bufferedImage;
        try {
            bufferedImage = ImageIO.read(imgFile);
            float pageW = page.getBBox().getWidth() - paddW * 2;// 文档真实宽
            float pageH = page.getBBox().getHeight() - paddH * 2;// 文档真实高
            float imageW = bufferedImage.getWidth();
            float imageH = bufferedImage.getHeight();
            float scale = resize(bufferedImage, pageW, pageH);// 缩放比例
            // 获取位置
            // 文档横坐标
            map.put("x", paddW + (pageW - imageW * scale) / 2);
            // 文档纵坐标
            map.put("y", pageH - imageH * scale + paddH);
            // 图片缩放后宽度
            map.put("width", imageW * scale);
            // 图片缩放后高度
            map.put("height", imageH * scale);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 获取图片缩放比例
     *
     * @param imgFile
     * @param pageW
     * @param pageH
     * @return
     */
    private static float resize(File imgFile, float pageW, float pageH) {
        BufferedImage bufferedImage;
        try {
            bufferedImage = ImageIO.read(imgFile);
            float width = bufferedImage.getWidth();
            float height = bufferedImage.getHeight();
            float scale = 1f;
            // 宽高都小于PDF,原样输出
            if (width <= pageW && height <= pageH) {
                return scale;
            }
            // 宽和高都大于PDF
            if (width > pageW && height > pageH) {
                return pageW / width < pageH / height ? pageW / width : pageH / height;
            }
            // 宽和高其一大于PDF
            return width > pageW ? pageW / width : pageH / height;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 1;
    }

    /**
     * 获取图片缩放比例
     *
     * @param bufferedImage
     * @param pageW
     * @param pageH
     * @return
     */
    private static float resize(BufferedImage bufferedImage, float pageW, float pageH) {
        float width = bufferedImage.getWidth();
        float height = bufferedImage.getHeight();
        float scale = 1f;
        // 宽高都小于PDF,原样输出
        if (width <= pageW && height <= pageH) {
            return scale;
        }
        // 宽和高都大于PDF
        if (width > pageW && height > pageH) {
            return pageW / width < pageH / height ? pageW / width : pageH / height;
        }
        // 宽和高其一大于PDF
        return width > pageW ? pageW / width : pageH / height;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值