pdf-box结合itext 实现特定的定制化操作pdf的需求

基本需求就是像已经有的pdf:pdf满足这样的条件,图片每页都是完整的即不可能出现一个图片在两页的问题,同时表格可能存在在两页的问题,当时真的出现也就正常覆盖就可以!

有这样的需求,在每页的底部1-3 厘米的地方 存在批量添加文字部分

距离底部的位置和添加的内容都是 txt文件,进行对应的读取就可以。

下一步:任务:前端整合 thymeleaf,部署服务器,结合  elementui vue  部署服务器

完整代码一:pdfbox无法解决中文乱码的问题:

公用的两个方法:

package com.special.weixin.pdf;

import lombok.experimental.Accessors;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * @author liuYC
 * @ClassName ReadTxt
 * @Description TODO
 * @date 2021/8/24 12:44
 */
public class ReadTxt {
    private static final String contentTxtPath = "D:\\fin_tech\\project-demo\\pdf-box-itext\\content.txt";
    private static final String numTxtPath = "D:\\fin_tech\\project-demo\\pdf-box-itext\\num.txt";

    /**
     * readByBuffer 读取 txt 文件内容
     */
    public static void readByBuffer(String filePath) {
        BufferedReader reader;
        try {
            reader = new BufferedReader(new FileReader(
                    filePath));
            String line = reader.readLine();
            while (line != null) {
                System.out.println(line);
                // read next line
                line = reader.readLine();
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * YL.txt
     * readByFile
     * //                if (line.equals("") || line == null) {
     * //                    continue;
     * //                }
     * <p>
     * List nullList = new ArrayList();
     * nullList.add(null);
     * nullList.add(" ");
     * nullList.add("");
     * allLines.removeAll(nullList);
     * // 去掉空行,当时实现有问题。
     * public static <T> List<T> removeNull(List<? extends T> oldList) {
     * <p>
     * // 你没有看错,真的是有 1 行代码就实现了
     * oldList.removeAll(Collections.singleton(null));
     * return (List<T>) oldList;
     * }
     */
    public static List<String> readByFile(String filePath) {
//        编码需要进行处理:
        List<String> allLines = new ArrayList<>();
        Charset charset = Charset.forName("GBK");
//        为什么会报红呢?
//        Charset charset = Charset.forName("Identity-H");
        try {
            allLines = Files.readAllLines(Paths.get(filePath), charset
            );
            List nullList = new ArrayList();
            nullList.add(null);
            nullList.add(" ");
            nullList.add("");
            allLines.removeAll(nullList);
            for (String line : allLines) {
                System.out.println(line);
            }
            System.out.println(allLines.size());
            System.out.println(allLines.size());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return allLines;
    }


    public static void main(String[] args) {
        ReadTxt.readByFile(contentTxtPath);
        System.out.println("=============================");
        ReadTxt.readByFile(numTxtPath);
    }
}

pdf-box实现,相关参考链接都已经给出:

 mvn:

<dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.23</version>
        </dependency>

代码: 

package com.special.weixin.pdf;


import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.apache.pdfbox.pdmodel.font.PDType1Font;


import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author liuYC
 * @ClassName AddPdfContent
 * @Description TODO
 * @date 2021/8/24 11:17
 */
public class AddPdfContent {
    /**
     * pdf add text in location special text
     * LIUYUHCAO
     * 将文本添加到现有PDF文档
     * 您可以使用PDFBox库向文档添加内容,这为您提供了一个名为PDPageContentStream的类,其中包含在PDFDocument的页面中插入文本,图像和其他类型内容所需的方法。
     * <p>
     * 以下是创建空文档并向其中的页面添加内容的步骤。
     * <p>
     * 第1步:加载现有文档
     * 您可以使用PDDocument类的load()方法加载现有文档。 因此,实例化此类并加载所需的文档,如下所示。
     * <p>
     * File file = new File("Path of the document");
     * PDDocument doc = document.load(file);
     * 1
     * 2
     * 3
     * 第2步:获取所需页面
     * 您可以使用getPage()方法在文档中获取所需的页面。 通过将索引传递给此方法来检索所需页面的对象,如下所示。
     * <p>
     * PDPage page = doc.getPage(1);
     * 1
     * 2
     * 第3步:准备内容流
     * 您可以使用类PDPageContentStream的对象插入各种数据元素。 您需要将文档对象和页面对象传递给此类的构造函数,因此,通过传递在前面步骤中创建的这两个对象来实例化此类,如下所示。
     * <p>
     * PDPageContentStream contentStream = new PDPageContentStream(doc, page);
     * 1
     * 2
     * 第4步:开始文本
     * 在PDF文档中插入文本时,可以使用PDPageContentStream类的beginText()和endText()方法指定文本的起点和终点,如下所示。
     * <p>
     * contentStream.beginText();
     * ………………………..
     * code to add text content
     * ………………………..
     * contentStream.endText();
     * 1
     * 2
     * 3
     * 4
     * 5
     * 6
     * 因此,使用beginText()方法开始文本,如下所示。
     * <p>
     * contentStream.beginText();
     * 1
     * 2
     * 第5步:设置文本的位置
     * 使用newLineAtOffset()方法,您可以在页面中的内容流上设置位置。
     * <p>
     * //Setting the position for the line
     * contentStream.newLineAtOffset(25, 700);
     * 1
     * 2
     * 3
     * 第6步:设置字体
     * 您可以使用PDPageContentStream类的setFont()方法将文本的字体设置为所需的样式,如下所示。 对于此方法,您需要传递字体的类型和大小。
     * <p>
     * contentStream.setFont( font_type, font_size );
     * 1
     * 2
     * 第7步:插入文本
     * 您可以使用PDPageContentStream类的ShowText()方法将文本插入到页面中,如下所示。 此方法以字符串形式接受所需的文本。
     * <p>
     * contentStream.showText(text);
     * 1
     * 2
     * 第8步:结束文本
     * 插入文本后,您需要使用PDPageContentStream类的endText()方法结束文本,如下所示。
     * <p>
     * contentStream.endText();
     * 1
     * 2
     * 第9步:关闭PDPageContentStream
     * 使用close()方法关闭PDPageContentStream对象,如下所示。
     * <p>
     * contentstream.close();
     * 1
     * 2
     * 第10步:保存文档
     * 添加所需内容后,使用PDDocument类的save()方法保存PDF文档,如以下代码块所示。
     * <p>
     * doc.save("Path");
     * 1
     * 2
     * 第11步:关闭文档
     * 最后,使用PDDocument类的close()方法关闭文档,如下所示。
     * <p>
     * doc.close();
     */
    private static final String pdfFileName = "D:\\fin_tech\\project-demo\\pdf-box-itext\\原料药叠图.pdf";
    //    private static  final  String pdfFileName = "D:\\fin_tech\\project-demo\\pdf-box-itext\\test.pdf";
    private static final String txtName = "D:\\fin_tech\\project-demo\\pdf-box-itext\\content.txt";
    private static final String numName = "D:\\fin_tech\\project-demo\\pdf-box-itext\\num.txt";

    public static void addTxtTextloc(String pdfFileName, String txtName, String pageInfo) throws IOException {
        //Loading an existing document
        File file = new File(pdfFileName);
        PDDocument document = PDDocument.load(file);
        //Retrieving the pages of the document
        PDPage page = document.getPage(0);
        /**
         * 获取总的page 的方法
         */
        final PDPageTree pages = document.getPages();
        System.out.println(pages);
        /**
         * 构造器解决原有文本被覆盖的问题!
         * https://blog.csdn.net/Jkcaotain/article/details/118943345?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162978504916780271517292%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162978504916780271517292&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v29_ecpm-2-118943345.pc_search_download_positive&utm_term=pdf%E6%B7%BB%E5%8A%A0%E6%96%87%E6%9C%AC%E5%90%8E%E6%96%87%E5%AD%97%E8%A6%86%E7%9B%96&spm=1018.2226.3001.4187
         * todo 解决备份的问题
         */
        PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, false, false);

        //Begin the Content stream
        contentStream.beginText();
        //Setting the font to the Content stream
        contentStream.setFont(PDType1Font.TIMES_ROMAN, 12);
        //Setting the position for the line
        contentStream.newLineAtOffset(100, 50);
        String text = "This is the sample document and we are adding content to it.";
        //Adding text in the form of string
        contentStream.showText(text);
        //Ending the content stream
        contentStream.endText();
        System.out.println("Content added");
        //Closing the content stream
        contentStream.close();
        //Saving the document
        document.save(new File(pdfFileName));
        //Closing the document
        document.close();
    }

    /**
     * 按照对应的传的对应的位置和对应的文本都是list
     *
     * @param pdfFileName
     * @throws IOException
     */
    public static void addTxtTextloc2(String pdfFileName, String txtName, String numName) throws IOException {
        //Loading an existing document
        File file = new File(pdfFileName);
        PDDocument document = PDDocument.load(file);
        //Retrieving the pages of the document
        List<String> txtNames = ReadTxt.readByFile(txtName);
        List<String> numNames = ReadTxt.readByFile(numName);

        if (txtNames.size() != numNames.size()) {
            System.out.println(" 内容和位置的txt 文件的信息数量不匹配");
            return;
        }
        for (int i = 0; i < txtNames.size(); i++) {
            PDPage page = document.getPage(i);
            PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, false, false);
            //Begin the Content stream
            contentStream.beginText();
            //Setting the font to the Content stream
            contentStream.setFont(PDType1Font.TIMES_ROMAN, 12);
            //Setting the position for the line
            loc loc = PdfUtils.listToMap().get(numNames.get(i));
            if (loc == null) {
                System.out.println(" map get 的值和预先需求的 1、2、3 cm 距离不一致");
            }
            contentStream.newLineAtOffset(loc.getTx(), loc.getTy());
//            String text = "This is the sample document and we are adding content to it.";
            //Adding text in the form of string
            System.out.println(i + "=================");
            System.out.println(new String(txtNames.get(i).getBytes(),StandardCharsets.UTF_8));
            contentStream.showText( new String(txtNames.get(i).getBytes(),StandardCharsets.UTF_8));
            //Ending the content stream
            contentStream.endText();
            System.out.println("Content added");
            //Closing the content stream
            contentStream.close();
        }
        /**
         * 构造器解决原有文本被覆盖的问题!
         * https://blog.csdn.net/Jkcaotain/article/details/118943345?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162978504916780271517292%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162978504916780271517292&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v29_ecpm-2-118943345.pc_search_download_positive&utm_term=pdf%E6%B7%BB%E5%8A%A0%E6%96%87%E6%9C%AC%E5%90%8E%E6%96%87%E5%AD%97%E8%A6%86%E7%9B%96&spm=1018.2226.3001.4187
         * todo 解决备份的问题
         */


        //Saving the document
        document.save(new File(pdfFileName));
        //Closing the document
        document.close();
    }

    public static void main(String[] args) throws IOException {
        AddPdfContent.addTxtTextloc2(pdfFileName, txtName, numName);
    }
// todo   指定坐标位置     和正常单位的换算
//    读取文件进行判断是否匹配
//    判断读取文字是否超出一行
//    进行匹配

// 如果pdf文件太大怎么解决?
//    比如更加的便利使用起来
//    前端操作页面
//
}

完整代码2:itext 解决了中文乱码问题,同时可以定制宋体,如果需要其他字体,而且对应的jar包没有,有博主,推荐重写字体相关类,当时没有尝试究竟能不能够实现!

mvn:

<dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.4.3</version>
        </dependency>
<dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
<!--            <scope>test</scope>-->
        </dependency>
package com.special.weixin.pdf;

import com.itextpdf.text.Chunk;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.*;
import org.junit.Test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

/**
 * @author liuYC
 * @ClassName AddContentByItext
 * @Description TODO
 * @date 2021/8/24 16:27
 */
public class AddContentByItext {
    private static final String txtName = "D:\\fin_tech\\project-demo\\pdf-box-itext\\content.txt";
    private static final String numName = "D:\\fin_tech\\project-demo\\pdf-box-itext\\num.txt";
    private static final String filePath = "D:\\fin_tech\\project-demo\\pdf-box-itext\\原料药叠图.pdf";
    private static final String savePath = "D:\\fin_tech\\project-demo\\pdf-box-itext\\itext\\原料药叠图OVER6.pdf";

    @Test
    public void addContent() throws IOException, DocumentException {

/**
 *  //中文字体,解决中文不能显示问题
 *         BaseFont bfChinese = BaseFont.createFont("C:/WINDOWS/Fonts/SIMYOU.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
 * //            BaseFont bfChinese = BaseFont.createFont("Helvetica", "Cp1252", BaseFont.NOT_EMBEDDED);
 *
 *         //蓝色字体
 *         Font blueFont = new Font(bfChinese);
 *         blueFont.setColor(BaseColor.BLUE);
 *         //绿色字体
 *         Font greenFont = new Font(bfChinese);
 *         greenFont.setColor(BaseColor.GREEN);
 *         //红色字体
 *         Font redFont = new Font(bfChinese);
 *         redFont.setColor(BaseColor.RED);
 *
 */
//        BaseFont baseFont =BaseFont.createFont("D:\\fin_tech\\project-demo\\pdf-box-itext\\itext\\simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);;
        BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", true);
//        BaseFont baseFont =BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-V",true);
//        BaseFont baseFont =BaseFont.createFont("C:/WINDOWS/Fonts/SIMYOU.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);;
//        BaseFont baseFont = BaseFont.createFont("Times-Roman", "UniGB-UCS2-H", true);
        Font font = new Font(baseFont);

        PdfReader reader = new PdfReader(new FileInputStream(filePath));
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(savePath));
//        final AcroFields fields = stamper.getAcroFields();
//        addTextToPdfCenter(fields,ps,value,key,baseFont);
        List<String> txtNames = ReadTxt.readByFile(txtName);
        List<String> numNames = ReadTxt.readByFile(numName);

        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            PdfContentByte over = stamper.getOverContent(i);
            ColumnText columnText = new ColumnText(over);
            /**
             *  Phrase hello = new Phrase("Hello World");
             *         PdfContentByte canvas = writer.getDirectContentUnder();
             *         ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT,
             *             hello, 36, 788, 0);
             */
            // llx 和 urx  最小的值决定离左边的距离. lly 和 ury 最大的值决定离下边的距离  13最小  24 最大
//            columnText.setSimpleColumn(150, 10, 350, 100);
//            columnText.setSimpleColumn(150, 10, 350, 110);
//            x 范围值在( 0-610)  56 size 610
            //居中的实现
            columnText.setSimpleColumn(305-((txtNames.get(i - 1).length())*610/56/2), 0, 610, (new Float(numNames.get(i - 1)) * 20));
//            columnText.setSimpleColumn(305-((txtNames.get(i - 1).length())/2)*(56/610), 0, 610, (new Float(numNames.get(i - 1)) * 20));
//            columnText.setSimpleColumn(380, 0, 400, (new Float(numNames.get(i - 1)) * 20));
//            columnText.set
//            columnText.setSimpleColumn(50, 10, 350, 50);
//            columnText.
//            columnText.setSimpleColumn(50, 100, 350, 300);
            System.out.println("length: "+txtNames.get(i - 1).length());
            Paragraph elements = new Paragraph(0, new Chunk(txtNames.get(i - 1)));
            // 设置字体,如果不设置添加的中文将无法显示
            elements.setFont(font);
//            columnText.setc();
            columnText.addElement(elements);
            columnText.go();
//            ColumnText
        }
        stamper.close();
    }

}

itext in action 读书笔记:

https://www.cnblogs.com/julyluo/archive/2012/07/29/2613822.html

itext in action 书籍链接:

链接:https://pan.baidu.com/s/1yH2PiPEon68eIBjDZvhE7Q 
提取码:z4mn 
--来自百度网盘超级会员V5的分享(过期私聊我)

itext生成PDF文件报错“Font 'STSong-Light' with 'UniGB-UCS2-H' is not recognized.”

https://developers.itextpdf.com/itext-5-examples

官方下载地址:https://developers.itextpdf.com/downloads

iText输出中文的三种字体选择方式

Itext 添加文本内容到已存在的PDF文件:

https://blog.csdn.net/qq_36537108/article/details/86635613

java转换字符串编码格式的方法

使用PDFBox向pdf中添加内容时,覆盖了pdf中原先的内容问题

开发团队的svn demo:不翻墙没法使用暂时:

https://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/printing/

Java spring boot 使用PDFBOX读取指定位置的文字:

https://blog.csdn.net/gavinbj/article/details/104441578

mvn的api文档:

https://pdfbox.apache.org/docs/2.0.13/javadocs/

参考博客:用pdf-box读出来,用itext进行写入的原因:就是中文乱码问题。

https://www.cnblogs.com/liangxinzhi/p/4275561.html

wiki的参考学习文档:

https://iowiki.com/pdfbox/pdfbox_adding_text.html

在特定的位置坐标添加内容参考链接:

https://www.freesion.com/article/74571133081/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

specialApe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值