JAVA itext 多种文件转pdf,进行合并 添加水印

结合网上各路大神代码汇总而来,如果需要将pdf统一格式,可将pdf转成图片后重新转为pdf合并至一起,使用itext的PdfCanvas未成功解决该问题,主要也是因为我菜且时间紧没空查文档了。对于itext7中的添加水印的方法也没有看完,故也尝试了itext5中的合并pdf及添加水印功能。

一些小问题:

1.RandomAccessSource not opened

itext5的pdf-copy功能存在某些文件复制进pdf后进行pdfDocument.close()时出现RandomAccessSource not opened的异常提示,切换至itext7的合并尝试后,并没有出现该问题。

2.PdfReader is not opened with owner password

该问题的出现是因为pdf被加密保护,如果需要继续读取则需要加上跳过密码对应的代码

itext5:

PdfReader.unethicalreading = true;

itext7:

PdfReader reader = new PdfReader(sourceFile);
reader.setUnethicalReading(true);

一. itext7版

1.依赖

                其中,itext7用于pdf合并,aspose-cells用于将excel转换为pdf,最后一个则为使用liberoffice将word、ppt、txt转换为pdf使用。

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext7-core</artifactId>
            <version>7.2.4</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>com.luhuiguo</groupId>
            <artifactId>aspose-cells</artifactId>
            <version>23.1</version>
        </dependency>
        <dependency>
            <groupId>com.liumapp.workable.converter</groupId>
            <artifactId>workable-converter</artifactId>
            <version>v1.2.0</version>
        </dependency>

2.文件格式转换及合并pdf

import com.aspose.cells.License;
import com.aspose.cells.PdfSaveOptions;
import com.aspose.cells.Workbook;
import com.hfzx.web.controller.common.config.HfzxConfig;
import com.hfzx.web.controller.common.exception.CustomException;
import com.hfzx.web.controller.common.utils.StringUtils;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.VerticalAlignment;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfStamper;
import com.liumapp.workable.converter.WorkableConverter;
import com.liumapp.workable.converter.core.ConvertPattern;
import com.liumapp.workable.converter.exceptions.ConvertFailedException;
import com.liumapp.workable.converter.factory.CommonConverterManager;
import com.liumapp.workable.converter.factory.ConvertPatternManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.jodconverter.document.DefaultDocumentFormatRegistry;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

/**
 * 合并pdf并加上水印
 * @date 2023-03-07
 */
@Slf4j
public class MergePdfUtil {

    /**
     * doc docx ppt pptx转pdf
     *
     * @param inputFile 源文件
     * @param pdfFile   输出文件
     */
    public static void word2PDF(String inputFile, String pdfFile) {
        File file = new File(inputFile);
        if (!file.exists()) {
            log.error("文件不存在");
            return;
        }
        FileInputStream is = null;
        FileOutputStream os = null;
        try {
            WorkableConverter converter = new WorkableConverter();
            ConvertPattern pattern = ConvertPatternManager.getInstance();
            is = new FileInputStream(file);
            os = new FileOutputStream(pdfFile);
            // 处理网络文件
            pattern.streamToStream(is, os);
            pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.DOCX);
            pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF);
            converter.setConverterType(CommonConverterManager.getInstance());
            converter.convert(pattern.getParameter());
        } catch (ConvertFailedException e) {
            log.error("文件:{},转换失败:{}", inputFile, e.getMessage());
        } catch (FileNotFoundException e) {
            log.error("文件:{}不存在或liceroffice未安装", inputFile);
        } finally {
            try {
                is.close();
                os.close();
            } catch (IOException e) {
                log.error("文件流关闭失败");
            }
        }
    }

    /**
     * excel转pdf
     */
    public static void excel2PDF(String excelPath, String pdfPath) {
        File file = new File(excelPath);
        if (!file.exists()) {
            throw new CustomException("文件不存在");
        }
        // 验证License
        if (!getLicense()) {
            return;
        }
        FileInputStream fileInputStream;
        try {
            fileInputStream = new FileInputStream(file);
            Workbook workbook = new Workbook(fileInputStream);
            File pdfFile = new File(pdfPath);
            PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
            //把excel所有内容放在一张PDF 页面上;
            pdfSaveOptions.setOnePagePerSheet(false);
            //把excel所有表头放在一张pdf上
            pdfSaveOptions.setAllColumnsInOnePagePerSheet(true);
            FileOutputStream fileOS = new FileOutputStream(pdfFile);
            workbook.save(fileOS, pdfSaveOptions);
            fileInputStream.close();
            fileOS.close();
        } catch (Exception e) {
            throw new CustomException(e.getMessage());
        }
    }

    /***
     * 图片转pdf
     * @param source
     * @param target
     */
    public static void img2Pdf(String source, String target) {
        File file = new File(source);
        if (!file.exists()) {
            log.error("文件不存在");
            return;
        }
        Document document;
        try {
            PdfWriter writer = new PdfWriter(target);
            PdfDocument pdf = new PdfDocument(writer);
            document = new Document(pdf);
            Image image = new Image(ImageDataFactory.create(source));
            image.setAutoScale(true);
            image.setAutoScaleHeight(true);
            image.setAutoScaleWidth(true);
            Paragraph p = new Paragraph().add(image);
            document.add(p);
            //关闭文档
            document.close();
            writer.close();
        } catch (Exception e) {
            log.error("图片:{},转pdf失败:{}", source, e.getMessage());
        }
    }

    /***
     * PDF文件转PNG图片,全部页数
     *
     * @param pdfFilePath pdf完整路径
     * @param dpi dpi越大转换后越清晰,相对转换速度越慢
     */
    public static List<String> pdf2Image(String pdfFilePath, int dpi) {
        File file = new File(pdfFilePath);
        PDDocument pdDocument = null;
        List<String> imgList = new ArrayList<>();
        try {
            String imgPdfPath = file.getParent();
            int dot = file.getName().lastIndexOf('.');
            // 获取图片文件名
            String imagePdfName = file.getName().substring(0, dot);

            pdDocument = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(pdDocument);
            /* dpi越大转换后越清晰,相对转换速度越慢 */
            StringBuffer imgFilePath;
            PdfReader reader = new PdfReader(pdfFilePath);
            int pages = pdDocument.getNumberOfPages();
            for (int i = 0; i < pages; i++) {
                String imgFilePathPrefix = imgPdfPath + File.separator + imagePdfName;
                imgFilePath = new StringBuffer();
                imgFilePath.append(imgFilePathPrefix);
                imgFilePath.append("_");
                imgFilePath.append((i + 1));
                imgFilePath.append(".png");
                File dstFile = new File(imgFilePath.toString());
                BufferedImage image = renderer.renderImageWithDPI(i, dpi);
                ImageIO.write(image, "png", dstFile);
                imgList.add(imgFilePath.toString());
            }
            pdDocument.close();
            return imgList;
        } catch (IOException e) {
            log.error("pdf转换图片异常:{}", e.getMessage());
        }
    }

    /**
     * 统一格式pdf
     *
     * @param savePath
     * @param readPath
     * @throws IOException
     */
    public static void setPageStyle(String savePath, String readPath) {
        PdfReader pdfReader = null;
        PdfDocument pdfDocument = null;
        PdfWriter pdfWriter = null;
        PdfDocument outPDfDoc = null;
        try {
            pdfReader = new PdfReader(readPath);
            pdfDocument = new PdfDocument(pdfReader);
            pdfWriter = new PdfWriter(savePath);
            outPDfDoc = new PdfDocument(pdfWriter);
            outPDfDoc.setDefaultPageSize(PageSize.A4);
            for (int i = 1; i < pdfDocument.getNumberOfPages() + 1; i++) {
                PdfPage page = pdfDocument.getPage(i);
                PdfFormXObject formXObject = page.copyAsFormXObject(outPDfDoc);
                float xPercent = PageSize.A4.getWidth() / page.getPageSize().getWidth();
                float yPercent = PageSize.A4.getHeight() / page.getPageSize().getHeight();
                PdfCanvas pdfCanvas = new PdfCanvas(outPDfDoc.addNewPage());
                pdfCanvas.addXObjectWithTransformationMatrix(formXObject, xPercent, 0, 0, yPercent, 0, 0);
            }

            pdfWriter.flush();
        } catch (Exception e) {
            log.error("转换异常:{}", e.getMessage());
        } finally {
            try {
                if (pdfReader != null) {
                    pdfReader.close();
                }
                if (pdfDocument != null) {
                    pdfDocument.close();
                }
                if (outPDfDoc != null) {
                    outPDfDoc.close();
                }
                if (pdfWriter != null) {
                    pdfWriter.close();
                }
            } catch (IOException e) {
                log.error("IO流关闭失败");
            }


        }
    }


    /***
     * 合并pdf并加上水印
     * @param sourceFileList 待合并文件
     * @param destinationPath 合并文件输出地址
     * @throws IOException
     */
    public static void mergePdf(String[] sourceFileList, String destinationPath) {
        File file = new File(destinationPath);
        //获取父目录
        File fileParent = file.getParentFile();
        if (!fileParent.exists()) {
            // 创建父目录文件夹
            fileParent.mkdirs();
        }
        try {
            PdfWriter writer = new PdfWriter(destinationPath);
            PdfDocument writerDoc = new PdfDocument(writer);
            //合并pdf
            for (String sourceFile : sourceFileList) {
                File readFile = new File(sourceFile);
                if (!readFile.exists()) {
                    log.error("文件不存在:" + sourceFile);
                    continue;
                }
                PdfReader reader = new PdfReader(sourceFile);
                //忽略pdf密码进行读取
                reader.setUnethicalReading(true);
                log.info("项目文书-读取文件:" + sourceFile);
                PdfDocument readerDoc = new PdfDocument(reader);
                for (int i = 1; i <= readerDoc.getNumberOfPages(); i++) {
                    //copy功能
                    PdfPage readerPage = readerDoc.getPage(i);
                    writerDoc.addPage(readerPage.copyTo(writerDoc));

                    /*//写入pdf并统一样式为A4 暂不使用
                    PdfPage page = readerDoc.getPage(i);
                    PdfFormXObject formXObject = page.copyAsFormXObject(writerDoc);
                    float xPercent = PageSize.A4.getWidth() /     page.getPageSize().getWidth();
                    float yPercent = PageSize.A4.getHeight() / page.getPageSize().getHeight();
                    PdfCanvas pdfCanvas = new PdfCanvas(writerDoc.addNewPage());
                    pdfCanvas.addXObjectWithTransformationMatrix(formXObject, xPercent, 0, 0, yPercent, 0, 0);*/
                }
                /*//合并
                PdfMerger merger = new PdfMerger(writerDoc);
                merger.merge(readerDoc, 1, readerDoc.getNumberOfPages());*/
                readerDoc.close();
                reader.close();
            }
            writerDoc.close();
        } catch (FileNotFoundException e) {
            log.error("文件生成失败:{}", e.getMessage());
        } catch (IOException e) {
            log.error("文件生成失败:{}", e.getMessage());
        }
    }

    /**
     * 验证License
     *
     * @return
     */
    private static boolean getLicense() {
        boolean result = false;
        try {
            // license路径
            InputStream license = Files.newInputStream("D:\\resource\\license.xml").toPath());
            License asposeLic = new License();
            asposeLic.setLicense(license);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * pdf添加水印
     *
     * @param inputFile         需要添加水印的文件
     * @param outputFile        添加完水印的文件存放路径
     * @param waterMarkName     需要添加的水印文字
     * @param imgWaterMarkUrl   水印图片
     * @param lastWaterMarkName 水印文字(暂定页脚左下角)
     * @param pageHeader        页眉
     * @param skipFirstPage     是否跳过首页
     * @return
     */
    public static boolean addWaterMark(String inputFile, String outputFile, String pageHeader, String waterMarkName
            , String lastWaterMarkName, String imgWaterMarkUrl, boolean skipFirstPage) {
        File file = new File(inputFile);
        if (!file.exists()) {
            return false;
        }
        PdfFont pdfFont = null;
        try {
            pdfFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
        } catch (IOException e) {
            log.error("pdf水印字体获取失败");
            return false;
        }
        try {
            FileOutputStream outputStream = new FileOutputStream(new File(outputFile));
            PdfWriter pdfWriter = new PdfWriter(outputStream);
            PdfDocument outDocument = new PdfDocument(pdfWriter);
            PdfReader pdfReader = new PdfReader(inputFile);
            PdfDocument redDocument = new PdfDocument(pdfReader);
            // 添加事件,该事件拥有添加水印
            outDocument.addEventHandler(PdfDocumentEvent.INSERT_PAGE, new PdfPageMarker(pdfFont, skipFirstPage));
            outDocument.addEventHandler(PdfDocumentEvent.INSERT_PAGE,
                    new PdfWaterMarker(pdfFont, lastWaterMarkName, waterMarkName, imgWaterMarkUrl));
            outDocument.addEventHandler(PdfDocumentEvent.INSERT_PAGE,
                    new PdfHeaderMarker(pdfFont, pageHeader, skipFirstPage));
            //获取总页数
            int numberOfPages = redDocument.getNumberOfPages();
            for (int i = 1; i <= numberOfPages; i++) {
                PdfPage page = redDocument.getPage(i);
                //复制每页内容添加到新的文件中
                outDocument.addPage(page.copyTo(outDocument));
            }
            outDocument.close();
            redDocument.close();
            pdfReader.close();
            log.info("水印添加成功");
            return true;
        } catch (IOException e) {
            log.error("水印生成失败");
            return false;
        }
    }
    
    public static void main(String[] args) {
        addWaterMark("D:\\test1.pdf", "D:\\test2.pdf", "页眉", "全页水印长长长", "页尾水印", null, true);
    }
}

3.添加页眉、页脚、水印,该事件不建议加在合并文件时使用,可能会出现一些文件加上水印、一些文件没加上水印的问题(我是懒狗)

对应copy来源:SpringBoot + Itext7 html转pdf 解决分页,表格被分割留出空白,水印,页眉页脚页码。_持伞走过故人路的博客-优快云博客

- 页眉

import com.hfzx.web.controller.common.utils.StringUtils;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.TextAlignment;

/**
 * PDF页眉
 *
 */
public class PdfHeaderMarker implements IEventHandler {

    private PdfFont pdfFont;
    private String title;

    private boolean skipFirstPage;

    public PdfHeaderMarker(PdfFont pdfFont, String title, boolean skipFirstPage) {
        this.pdfFont = pdfFont;
        this.title = title;
        this.skipFirstPage = skipFirstPage;
    }

    @Override
    public void handleEvent(Event event) {
        if (StringUtils.isNotEmpty(title)) {
            PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
            PdfDocument pdf = docEvent.getDocument();
            PdfPage page = docEvent.getPage();
            int pageNumber = pdf.getPageNumber(page);
            // 封面不展示页眉页脚
            if (skipFirstPage ? pageNumber != 1 : true) {
                Rectangle pageSize = page.getPageSize();
                PdfCanvas pdfCanvas = new PdfCanvas(page.getLastContentStream(), page.getResources(), pdf);
                Canvas canvas = new Canvas(pdfCanvas, pageSize);
                float x = (pageSize.getLeft() + pageSize.getRight()) / 2;
                float y = pageSize.getTop() - 25;
                Paragraph p = new Paragraph(title)
                        .setFontSize(12)
                        .setFont(pdfFont);
                // 顶部中间位置
                canvas.showTextAligned(p, x, y, TextAlignment.CENTER);
                canvas.close();
            }
        }
    }

}

-页脚

import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.TextAlignment;

/**
 * pdf 页脚
 *
 */
public class PdfFooterMarker implements IEventHandler {

    private PdfFont pdfFont;

    private boolean skipFirstPage;

    public PdfFooterMarker(PdfFont pdfFont, boolean skipFirstPage) {
        this.pdfFont = pdfFont;
        this.skipFirstPage = skipFirstPage;
    }

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
        PdfDocument pdf = docEvent.getDocument();
        PdfPage page = docEvent.getPage();
        int pageNumber = pdf.getPageNumber(page);
        // 封面不展示页眉页脚
        if (skipFirstPage ? pageNumber != 1 : true) {
            pageNumber = skipFirstPage ? pageNumber - 1 : pageNumber;
            Rectangle pageSize = page.getPageSize();
            PdfCanvas pdfCanvas = new PdfCanvas(page.getLastContentStream(), page.getResources(), pdf);
            Canvas canvas = new Canvas(pdfCanvas, pageSize);
            float x = (pageSize.getLeft() + pageSize.getRight()) / 2;
            float y = pageSize.getBottom() + 15;
            Paragraph p = new Paragraph("第" + pageNumber + "页")
                    .setFontSize(12)
                    .setFont(pdfFont);
            // 底部中间位置
            canvas.showTextAligned(p, x, y, TextAlignment.CENTER);
            canvas.close();
        }
    }

}

-水印

import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.VerticalAlignment;
import org.apache.commons.lang3.StringUtils;

import java.io.*;

/***
 * pdf 水印
 */
public class PdfWaterMarker implements IEventHandler {

    private PdfFont pdfFont;
    private String waterContent;

    private String waterAllContent;
    private String waterImgPath;

    /**
     * 全页水印字体大小
     */
    private static final int WATER_ALL_FONT_SIZE = 30;
    /**
     * 全页水印字体透明度
     */
    private static float OPACITY = 0.2f;
    /**
     * 全页水印倾斜角度(0-360)
     */
    private static int ANGLE = 120;
    /**
     * 数值越大每页竖向水印越少
     */
    private static int HEIGHT_DENSITY = 6;

    /**
     * 高度倍数
     */
    private static float HEIGHT_MULTIPLE = 2;
    /**
     * 数值越大每页横向水印越少
     */
    private static int WIDTH_DENSITY = 3;

    /**
     * 宽度倍数
     */
    private static float WIDTH_MULTIPLE = 1.5f;


    public PdfWaterMarker(PdfFont pdfFont, String waterContent, String waterAllContent, String waterImgPath) {
        this.pdfFont = pdfFont;
        this.waterContent = waterContent;
        this.waterAllContent = waterAllContent;
        this.waterImgPath = waterImgPath;
    }

    @Override
    public void handleEvent(Event event) {

        PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
        PdfDocument pdf = docEvent.getDocument();
        PdfPage page = docEvent.getPage();
        Rectangle pageSize = page.getPageSize();
        PdfCanvas pdfCanvas = new PdfCanvas(page.getLastContentStream(), page.getResources(), pdf);
        Canvas canvas = new Canvas(pdfCanvas, pageSize);
        int pageNumber = pdf.getPageNumber(page);
        //页脚水印
        if (StringUtils.isNotBlank(waterContent)) {
            Paragraph waterMarker = new Paragraph(waterContent)
                    .setFont(pdfFont)
                    .setOpacity(.5f)
                    .setFontSize(13);
            // 右下角位置
            canvas.showTextAligned(waterMarker, pageSize.getRight() - 150,
                    pageSize.getBottom() + 15, pdf.getNumberOfPages(),
                    TextAlignment.LEFT, VerticalAlignment.BOTTOM, 0);
        }
        //全页水印
        if (StringUtils.isNotBlank(waterAllContent)) {
            Paragraph waterMarker = new Paragraph(waterAllContent)
                    .setFont(pdfFont)
                    .setOpacity(OPACITY)
                    .setFontSize(WATER_ALL_FONT_SIZE);
            float textH = WATER_ALL_FONT_SIZE;
            float textW = WATER_ALL_FONT_SIZE * waterAllContent.length();
            for (float height = textH; height < page.getPageSize().getHeight() * HEIGHT_MULTIPLE;
                 height = height + textH * HEIGHT_DENSITY) {
                for (float width = textW; width < page.getPageSize().getWidth() * WIDTH_MULTIPLE + textW;
                     width = width + textW * WIDTH_DENSITY) {
                    //第一行贴左展示
                    canvas.showTextAligned(waterMarker, width - textW + 5, height - textH, pdf.getNumberOfPages(),
                            TextAlignment.LEFT, VerticalAlignment.BOTTOM, ANGLE);
                    //第二行跨行展示
                    canvas.showTextAligned(waterMarker, width, height - textH, pdf.getNumberOfPages(),
                            TextAlignment.LEFT, VerticalAlignment.BOTTOM, ANGLE);
                }
            }
        }

        // 水印图片
        Image waterImg = null;
        if (StringUtils.isNotBlank(waterImgPath)) {
            try {
                InputStream inputStream = returnInputStream(waterImgPath);
                if (inputStream != null) {
                    ImageData waterImgData = ImageDataFactory.create(toByteArray(inputStream));
                    waterImg = new Image(waterImgData);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        // 图片水印
        if (waterImg != null) {
            int length = waterContent.length();
            // 设置坐标 X Y
            waterImg.setFixedPosition(pdf.getNumberOfPages(), pageSize.getRight() - (168 + length),
                    pageSize.getBottom() + 30);
            // 设置等比缩放
            ;// 自定义大小
            waterImg.scaleAbsolute(100, 100);
            // 写入图片水印
            canvas.add(waterImg);
        }

        canvas.close();
    }

    public static byte[] toByteArray(InputStream input) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[4096];
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
        }
        return output.toByteArray();
    }

    public static InputStream returnInputStream(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            return null;
        }
        InputStream inputStream = new FileInputStream(file);
        return inputStream;
    }

}

二、 itext5

就附个代码了,合并和水印网上都有

import com.aspose.cells.License;
import com.aspose.cells.PdfSaveOptions;
import com.aspose.cells.Workbook;
import com.hfzx.web.controller.common.config.HfzxConfig;
import com.hfzx.web.controller.common.exception.CustomException;
import com.hfzx.web.controller.common.utils.StringUtils;
import com.hfzx.web.controller.common.utils.file.FileUtils;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.liumapp.workable.converter.WorkableConverter;
import com.liumapp.workable.converter.core.ConvertPattern;
import com.liumapp.workable.converter.exceptions.ConvertFailedException;
import com.liumapp.workable.converter.factory.CommonConverterManager;
import com.liumapp.workable.converter.factory.ConvertPatternManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.jodconverter.document.DefaultDocumentFormatRegistry;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;

/**
 * 合并pdf并加上水印
 *
 */
@Slf4j
public class MergePDFUtilTmp {

    //水印字体透明度
    private static float opacity = 0.2f;
    //水印字体大小
    private static int fontsize = 30;
    //水印倾斜角度(0-360)
    private static int angle = 30;
    //数值越大每页竖向水印越少
    private static int heightDensity = 12;
    //数值越大每页横向水印越少
    private static int widthDensity = 6;

    /***
     * 图片
     */
    public static String[] PHOTO = new String[]{
            "bmp", "jpg", "jpeg", "png", "tif", "gif", "psd", "pcx", "tga", "exif", "fpx", "svg", "ai", "eps", "ufo", "dxf", "pcd", "cdr",
            "raw", "wmf", "webp", "avif"};
    /***
     * 文档
     */
    public static String[] WORD = new String[]{"doc", "docx", "txt"};
    /**
     * excel
     */
    public static String[] EXCEL = new String[]{"xls", "xlsx"};
    /**
     * ppt
     */
    public static String[] PPT = new String[]{"ppt", "pptx"};


    public static void trans(String filePath, String pdfPath, String type) {
        toPdf(filePath, pdfPath, type);
    }

    //转换
    private static void toPdf(String filePath, String pdfPath, String type) {
        if ("word".equals(type)) {
            word2PDF(filePath, pdfPath);
        } else if ("excel".equals(type)) {
            excel2PDF(filePath, pdfPath);
        } else if ("ppt".equals(type)) {
            word2PDF(filePath, pdfPath);
        } else if ("photo".equals(type)) {
            convert(filePath, pdfPath);
        }
    }

    private static void word2PDF(String inputFile, String pdfFile) {
        File file = new File(inputFile);
        if (!file.exists()) {
            return;
        }
        FileInputStream is = null;
        FileOutputStream os = null;
        try {
            WorkableConverter converter = new WorkableConverter();
            ConvertPattern pattern = ConvertPatternManager.getInstance();
            is = new FileInputStream(file);
            os = new FileOutputStream(pdfFile);
            // 处理网络文件
            pattern.streamToStream(is, os);
            pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.DOCX);
            pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF);
            converter.setConverterType(CommonConverterManager.getInstance());
            boolean result = converter.convert(pattern.getParameter());
        } catch (ConvertFailedException e) {
            log.error("文件转换失败");
        } catch (FileNotFoundException e) {
            log.error("文件不存在或liberoffice不存在");
        } finally {
            try {
                is.close();
                os.close();
            } catch (IOException e) {
                log.error("文件流关闭失败");
            }
        }
    }

    public static void excelFirstHandel(String excelPath, String pdfPath) {
        // 获取图片文件名
        String tempPdfPath = pdfPath.substring(0, pdfPath.lastIndexOf(".")) + "temp.pdf";
        excel2PDF(excelPath, tempPdfPath);
        String img = pdf2Image(tempPdfPath, 100);
        if (StringUtils.isNotEmpty(img)) {
            convert(img, pdfPath);
            FileUtils.deleteFile(img);
        }
    }

    public static void excel2PDF(String excelPath, String pdfPath) {
        File file = new File(excelPath);
        if (!file.exists()) {
            return;
        }
        // 验证License
        if (!getLicense()) {
            return;
        }
        FileInputStream fileInputStream;
        try {
            fileInputStream = new FileInputStream(file);
            Workbook workbook = new Workbook(fileInputStream);
            File pdfFile = new File(pdfPath);
            PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
            //把excel所有内容放在一张PDF 页面上;
            pdfSaveOptions.setOnePagePerSheet(false);
            //把excel所有表头放在一张pdf上
            pdfSaveOptions.setAllColumnsInOnePagePerSheet(true);
            FileOutputStream fileOS = new FileOutputStream(pdfFile);
            workbook.save(fileOS, pdfSaveOptions);
            fileInputStream.close();
            fileOS.close();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    /***
     * PDF文件转PNG图片,全部页数
     *
     * @param pdfFilePath pdf完整路径
     * @param dpi dpi越大转换后越清晰,相对转换速度越慢
     */
    public static String pdf2Image(String pdfFilePath, int dpi) {
        File file = new File(pdfFilePath);
        PDDocument pdDocument = null;
        try {
            String imgPdfPath = file.getParent();
            int dot = file.getName().lastIndexOf('.');
            // 获取图片文件名
            String imagePdfName = file.getName().substring(0, dot);

            pdDocument = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(pdDocument);
            /* dpi越大转换后越清晰,相对转换速度越慢 */
            StringBuffer imgFilePath;
//            PdfReader reader = new PdfReader(pdfFilePath);
//            int pages = reader.getNumberOfPages();
//            for (int i = 0; i < pages; i++) {
//                String imgFilePathPrefix = imgPdfPath + File.separator + imagePdfName;
//                imgFilePath = new StringBuffer();
//                imgFilePath.append(imgFilePathPrefix);
//                imgFilePath.append("_");
//                imgFilePath.append((i + 1));
//                imgFilePath.append(".png");
//                File dstFile = new File(imgFilePath.toString());
//                BufferedImage image = renderer.renderImageWithDPI(i, dpi);
//                ImageIO.write(image, "png", dstFile);
//            }
            String imgFilePathPrefix = imgPdfPath + File.separator + imagePdfName;
            imgFilePath = new StringBuffer();
            imgFilePath.append(imgFilePathPrefix);
            imgFilePath.append(".png");
            File dstFile = new File(imgFilePath.toString());
            BufferedImage image = renderer.renderImageWithDPI(0, dpi);
            ImageIO.write(image, "png", dstFile);
            pdDocument.close();
            return imgFilePath.toString();
        } catch (IOException e) {

            throw new CustomException(e.getMessage());
        }
    }


    private static boolean getLicense() {
        boolean result = false;
        try {
            // license路径
            InputStream license = Files.newInputStream(new File(HfzxConfig.getDownloadPath() + "resource/license.xml").toPath());
            License aposeLic = new License();
            aposeLic.setLicense(license);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    //图片转pdf
    public static void convert(String source, String target) {
        File file = new File(source);
        if (!file.exists()) {
            return;
        }
        Document document = new Document();
        //设置文档页边距
        document.setMargins(40, 57, 5, 57);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(target);
            PdfWriter.getInstance(document, fos);
            //打开文档
            document.open();
            //获取图片的宽高
            Image image = Image.getInstance(source);
            float imageHeight = image.getScaledHeight();
            float imageWidth = image.getScaledWidth();
            // 设置图片自适应页面宽高
            Rectangle pageSize = document.getPageSize();
            float width = pageSize.getWidth();
            float height = pageSize.getHeight();
            float wSize = imageWidth / width;
            if (wSize > 1f) {
                image.scaleAbsolute(imageWidth / wSize, imageHeight / wSize);
            }
            float hSize = image.getScaledHeight()/height;
            if (hSize > 1f) {
                image.scaleAbsolute(image.getScaledWidth() / hSize, image.getScaledHeight() / hSize);
            }
            //图片居中
            image.setAlignment(Image.ALIGN_CENTER);
            //新建一页添加图片
            document.newPage();
            document.add(image);
        } catch (Exception ioe) {
            log.error("图片不存在");
        } finally {
            //关闭文档
            document.close();
            try {
                fos.flush();
                fos.close();
            } catch (IOException e) {
                log.error("文件流关闭失败");
            }
        }
    }

    public static boolean mergePdfFiles(String[] files, String newfile) {
        boolean retValue = false;
        Document document = null;
        PdfReader first = null;
        //跳过密码
        PdfReader.unethicalreading = true;
        // 临时生成文件路径
        File f = new File(newfile);
        //获取父目录
        File fileParent = f.getParentFile();
        if (!fileParent.exists()) {
            // 创建父目录文件夹
            fileParent.mkdirs();
        }
        try {
            first = new PdfReader(files[0]);
            document = new Document(first.getPageSize(1));
            PdfCopy copy = new PdfCopy(document, new FileOutputStream(newfile));
            document.open();

            for (int i = 0; i < files.length; i++) {
                File c = new File(files[i]);
                if (!c.exists()) {
                    log.error("文件不存在:" + files[i]);
                    continue;
                }
                PdfReader reader = null;
                try {
                    reader = new PdfReader(files[i]);
                    int n = reader.getNumberOfPages();
                    for (int j = 1; j <= n; j++) {
                        document.newPage();
                        PdfImportedPage page = copy.getImportedPage(reader, j);
                        copy.addPage(page);
                    }
                    log.info("文件合并成功:" + files[i]);
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    log.error("存在无法复制文件:{},对应文件目录:{}", e.getMessage(), files[i]);
                } finally {
                    if (null != reader) {
                        reader.close();
                    }
                    if (null != first) {
                        first.close();
                    }
                }

            }
            retValue = true;
        } catch (Exception e) {
            log.error("合并文件失败:" + e.getMessage());
        } finally {
            if (null != document) {
                document.close();
            }
            if (null != first) {
                first.close();
            }
        }
        return retValue;
    }

    /**
     * pdf添加水印
     *
     * @param inputFile     需要添加水印的文件
     * @param outputFile    添加完水印的文件存放路径
     * @param waterMarkName 需要添加的水印文字
     * @param cover         是否覆盖
     * @return
     */
    public static boolean addWaterMark(String inputFile, String outputFile, String waterMarkName, boolean cover) {
        if (!cover) {
            File file = new File(outputFile);
            if (file.exists()) {
                return true;
            }
        }
        File file = new File(inputFile);
        if (!file.exists()) {
            return false;
        }

        PdfReader reader = null;
        PdfStamper stamper = null;
        try {
            reader = new PdfReader(inputFile);
            stamper = new PdfStamper(reader, new FileOutputStream(outputFile));
            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
            Rectangle pageRect = null;
            PdfGState gs = new PdfGState();
            //这里是透明度设置
            gs.setFillOpacity(opacity);
            //这里是条纹不透明度
            gs.setStrokeOpacity(0.2f);
            int total = reader.getNumberOfPages() + 1;
            System.out.println("Pdf页数:" + reader.getNumberOfPages());
            JLabel label = new JLabel();
            FontMetrics metrics;
            int textH = 0;
            int textW = 0;
            label.setText(waterMarkName);
            metrics = label.getFontMetrics(label.getFont());
            //字符串的高,   只和字体有关
            textH = metrics.getHeight();
            //字符串的宽
            textW = metrics.stringWidth(label.getText());
            PdfContentByte under;
            //循环PDF,每页添加水印
            for (int i = 1; i < total; i++) {
                pageRect = reader.getPageSizeWithRotation(i);
                //在内容上方添加水印
                under = stamper.getOverContent(i);
                under.saveState();
                under.setGState(gs);
                under.beginText();
                //这里是水印字体大小
                under.setFontAndSize(base, fontsize);
                for (int height = textH; height < pageRect.getHeight() * 2; height = height + textH * heightDensity) {
                    for (int width = textW; width < pageRect.getWidth() * 1.5 + textW; width = width + textW * widthDensity) {
                        // rotation:倾斜角度
                        under.showTextAligned(Element.ALIGN_LEFT, waterMarkName, width - textW, height - textH, angle);
                    }
                }
                //添加水印文字
                under.endText();
            }
            System.out.println("添加水印成功!");
            return true;
        } catch (IOException e) {
            log.error("添加水印失败!错误信息为: " + e);
            return false;
        } catch (DocumentException e) {
            log.error("添加水印失败!错误信息为: " + e);
            return false;
        } finally {
            //关闭流
            if (stamper != null) {
                try {
                    stamper.close();
                } catch (DocumentException e) {
                    log.error("文件流关闭失败");
                } catch (IOException e) {
                    log.error("文件流关闭失败");
                }
            }
            if (reader != null) {
                reader.close();
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值