这两天碰到了一个根据模板导出pdf的需求,研究了几天以后,发现网上的资料不太齐全,主要是没找到既根据模板导出,又可以动态增加页数的例子。只能通过各种资料结合来实现这个需求了(其实是懒得看iText英文文档,这个以后得改过来)。
下面先来说下pdf导出主要的两种方式:
1.直接使用iText的api,写出原生的pdf文档,但是样式和排版很难控制,比较方便的是,可以动态的添加文档数据,还可以增加页数等操作。关于样式和排版可以通过结合XmlWorker,从HTML模板生成PDF。
2.根据pdf模板导出,这里会涉及到使用adobe acrobat这个软件。通过adobe acrobat来制作表单域,然后在应用程序里动态向表单域添加数据。
(1)在adobe acrobat中打开一个pdf文档,然后点击右侧的“准备表单”,选择文件后点击“开始”
图片步骤为:
java根据模板导出pdf(动态增加模板页数)
java根据模板导出pdf(动态增加模板页数)
(2).在页面上新建表单域,可以通过右键-属性,修改表单域的设置,这里新建了两个name为“title”和“img”的文本域
java根据模板导出pdf(动态增加模板页数)
java根据模板导出pdf(动态增加模板页数)
(3).将设置了表单域的pdf文档保存即可
3.现在就是开始写java代码了,首先需要在pom文件里引入两个itext的jar包,如下所示:

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.6</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
        </dependency>

(1)多页导出,包含图片。如果导出的中文无法显示,需要重新设置字体。

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class PdfTest {
    // 利用模板生成pdf
    public static void fillTemplate() {
        // 原pdf模板路径
        String templatePath = "D:/old.pdf";
        // 生成的新文件路径
        String newPDFPath = "D:/new.pdf";
        //图片路径
        String imgPath = "D:/test.jpg";
        FileOutputStream out;
        int num = 2;//页数
        ByteArrayOutputStream bos[] = new ByteArrayOutputStream[num];
        try {
            out = new FileOutputStream(newPDFPath);// 输出流
            Document doc = new Document();   //新建一个文档
            PdfCopy copy = new PdfCopy(doc, out); //用于保存原页面内容,然后输出
            doc.open();

            for (int i = 0; i < num; i++) {
                bos[i] = new ByteArrayOutputStream();
                PdfReader reader = new PdfReader(templatePath);// 读取pdf模板
                PdfStamper stamper = new PdfStamper(reader, bos[i]); //生成输出流
                AcroFields form = stamper.getAcroFields(); //获取文本域
                form.setField("title", "这是标题");

                int pageNo = form.getFieldPositions("img").get(0).page;
                Rectangle rectangle = form.getFieldPositions("img").get(0).position;
                float x = rectangle.getLeft();
                float y = rectangle.getBottom();
                //根据路径读取图片
                Image image = Image.getInstance("D:/test.jpg");
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(rectangle.getWidth(), rectangle.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
                stamper.setFormFlattening(true);// 如果为false那么生成的PDF文件还能编辑,一定要设为true
                stamper.close();

            }
            PdfImportedPage page = null;
            for (int i = 0; i < num; i++) {
                page = copy.getImportedPage(new PdfReader(bos[i].toByteArray()), i + 1);
                copy.addPage(page);
            }
            doc.close();
            out.close();
        } catch (IOException e) {
            System.out.println("导出异常");
        } catch (DocumentException e) {
            System.out.println("文档异常");
        }

    }

    public static void main(String[] args) {
        fillTemplate();
    }
}

(2)此时的需求是需要根据应用程序,动态复制第二页的模板,那么代码改为下面这种

// 利用模板生成pdf
    public static void fillTemplate() {
        // 原pdf模板路径
        String templatePath = "D:/old.pdf";
        // 生成的新文件路径
        String newPDFPath = "D:/new.pdf";
        //图片路径
        String imgPath = "D:/test.jpg";
        FileOutputStream out;
        int num = 4;//页数
        ByteArrayOutputStream bos[] = new ByteArrayOutputStream[num];
        try {
            out = new FileOutputStream(newPDFPath);// 输出流
            Document doc = new Document();   //新建一个文档
            PdfCopy copy = new PdfCopy(doc, out); //用于保存原页面内容,然后输出
            doc.open();

            for (int i = 0; i < 2; i++) {
                bos[i] = new ByteArrayOutputStream();
                PdfReader reader = new PdfReader(templatePath);// 读取pdf模板
                PdfStamper stamper = new PdfStamper(reader, bos[i]); //生成输出流
                AcroFields form = stamper.getAcroFields(); //获取文本域
                form.setField("title", "这是标题");

                int pageNo = form.getFieldPositions("img").get(0).page;
                Rectangle rectangle = form.getFieldPositions("img").get(0).position;
                float x = rectangle.getLeft();
                float y = rectangle.getBottom();
                //根据路径读取图片
                Image image = Image.getInstance("D:/test.jpg");
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(rectangle.getWidth(), rectangle.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
                stamper.setFormFlattening(false);// 如果为false那么生成的PDF文件还能编辑,一定要设为true
                stamper.close();

            }
            //将之前的两次输出
            PdfImportedPage page = null;
            for (int i = 0; i < 2; i++) {
                page = copy.getImportedPage(new PdfReader(bos[i].toByteArray()), i + 1);
                copy.addPage(page);
            }
            //复制两次
            for (int j=0;j<2;j++){
                PdfReader reader = new PdfReader(templatePath);// 重新读取pdf模板
                bos[j]=new ByteArrayOutputStream();
                reader.selectPages("2-2");//截取模板的第二页
                PdfStamper stamper = new PdfStamper(reader, bos[j]);
                AcroFields fields = stamper.getAcroFields();
                fields.setField("img", "这是第"+j+"张图片");
                page = copy.getImportedPage(reader, 1);//输出当前页
                copy.addPage(page);
            }

            doc.close();
            out.close();
        } catch (IOException e) {
            System.out.println("导出异常");
        } catch (DocumentException e) {
            System.out.println("文档异常");
        }

这就是我的实现方式了,如果你有更好的方式,欢迎提出来。
下面粘贴几个参考链接:
1.java根据模板生成pdf文件并导出 https://blog.csdn.net/top__one/article/details/65442390
2.java根据模板动态生成PDF https://segmentfault.com/a/1190000009160184

相关文章: