java之數據填充PDF模板

聲明:因爲業務場景須要,因此根據一個網友的完成的。java

一、既然要使用PDF模板填充,那麼就須要製做PDF模板,能夠使用Adobe Acrobat DC,下載地址https://carrot.ctfile.com/dir/11269771-27158812-194d66/29433907/ (使用特別破解版),安裝步驟就省略了。apache

二、開始製做模板數組

  a)使用wps製做一個表格,並轉爲PDF文件保存ide

  

  b)使用Adobe Acrobat DC打開保存的PDF文件,而後搜索 "準備表單" ,點擊 」準備表單「,而後出來表單域工具

三、程序部分ui

  a)依賴spa

     <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.10</version>
        </dependency>

        <!-- itextpdf 依賴包start -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.10</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <!-- itextpdf 依賴包end -->

        <!--pdf 轉圖片 start -->
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.11</version>
        </dependency>

        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.2</version>
        </dependency>
        <!--pdf 轉圖片 end -->

  b)工具類 ImageThumbUtils,該類主要是用於將pdf轉爲圖片,若是不須要能夠不添加code

package com.yangwj.demo.controller;

import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;

import javax.imageio.ImageIO;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * 圖片縮略、裁剪、添加水印。
 */
public class ImageThumbUtils {

    /**
     * 縮略圖片,圖片質量爲源圖的80%
     *
     * @param originalImgPath
     *            源圖片存儲路徑
     * @param w
     *            圖片壓縮後的寬度
     * @param h
     *            圖片壓縮後的高度
     * @param targetImgPath
     *            縮略圖的存放路徑
     */
    public static void thumbImage(String originalImgPath, int w, int h, String targetImgPath) throws Exception {
        thumbImage(new FileInputStream(originalImgPath), w, h, targetImgPath, 0.8);
    }

    /**
     * 縮略圖片,圖片質量爲源圖的80%
     *
     * @param originalImgData
     *            源圖片字節數
     * @param w
     *            圖片壓縮後的寬度
     * @param h
     *            圖片壓縮後的高度
     * @param targetImgPath
     *            縮略圖的存放路徑
     */
    public static void thumbImage(byte[] originalImgData, int w, int h, String targetImgPath) throws Exception {
        thumbImage(new ByteArrayInputStream(originalImgData), w, h, targetImgPath, 0.8);
    }

    /**
     * 按比例壓縮文件
     * @param originalImgData 源文件
     * @param compressQalitiy 壓縮比例
     * @param targetImgPath 目標路徑
     */
    public static void thumbImage(byte[] originalImgData, double compressQalitiy, String targetImgPath) throws Exception {
        Thumbnails.of(new ByteArrayInputStream(originalImgData)).scale(1f).outputQuality(compressQalitiy).toFile(targetImgPath);
    }

    /**
     * 按尺寸比例縮略
     *
     * @param originalInputSteam
     *            源圖輸入流
     * @param w
     *            縮略寬
     * @param h
     *            縮略高
     * @param targetImgPath
     *            縮略圖存儲路徑
     * @param compressQalitiy
     *            縮略質量比例,0~1之間的數
     */
    public static void thumbImage(InputStream originalInputSteam, int w, int h, String targetImgPath, double compressQalitiy) throws Exception {
        thumbImage(originalInputSteam, w, h, targetImgPath, compressQalitiy, true);
    }

    /**
     *
     * @param originalImgInputSteam
     *            源圖片輸入流
     * @param w
     *            圖片壓縮後的寬度
     * @param h
     *            圖片壓縮後的高度
     * @param targetImgPath
     *            縮略圖的存放路徑
     * @param compressQalitiy
     *            壓縮比例,0~1之間的double數字
     * @param keepAspectRatio
     *            是否保持等比例壓縮,是true,不是false
     */
    public static void thumbImage(InputStream originalImgInputSteam, int w, int h, String targetImgPath, double compressQalitiy,
                                  boolean keepAspectRatio) throws Exception {
        Thumbnails.of(originalImgInputSteam).size(w, h).outputQuality(Double.valueOf(compressQalitiy)).keepAspectRatio(true).toFile(targetImgPath);
    }

    /**
     * 圖片裁剪
     *
     * @param originalImgPath
     *            源圖片路徑
     * @param targetImgPath
     *            新圖片路徑
     * @param position
     *            位置 0正中間,1中間左邊,2中間右邊,3底部中間,4底部左邊,5底部右邊,6頂部中間,7頂部左邊,8頂部右邊,
     *            其餘爲默認正中間
     * @param w
     *            裁剪寬度
     * @param h
     *            裁剪高度
     * @throws Exception
     */
    public static void crop(String originalImgPath, int position, int w, int h, String targetImgPath) throws Exception {
        Thumbnails.of(originalImgPath).sourceRegion(getPositions(position), w, h).size(w, h).outputQuality(1).toFile(targetImgPath);
    }

    /**
     * 給圖片添加水印
     *
     * @param originalImgPath
     *            將被添加水印圖片 路徑
     * @param targetImgPath
     *            含有水印的新圖片路徑
     * @param watermarkImgPath
     *            水印圖片
     * @param position
     *            位置 0正中間,1中間左邊,2中間右邊,3底部中間,4底部左邊,5底部右邊,6頂部中間,7頂部左邊,8頂部右邊,
     *            其餘爲默認正中間
     * @param opacity
     *            不透明度,取0~1之間的float數字,0徹底透明,1徹底不透明
     * @throws Exception
     */
    public static void watermark(String originalImgPath, String watermarkImgPath, int position, float opacity, String targetImgPath)
            throws Exception {
        Thumbnails.of(originalImgPath).watermark(getPositions(position), ImageIO.read(new File(watermarkImgPath)), opacity).scale(1.0)
                .outputQuality(1).toFile(targetImgPath);
    }

    private static Positions getPositions(int position) {
        Positions p = Positions.CENTER;
        switch (position) {
            case 0: {
                p = Positions.CENTER;
                break;
            }
            case 1: {
                p = Positions.CENTER_LEFT;
                break;
            }
            case 2: {
                p = Positions.CENTER_RIGHT;
                break;
            }
            case 3: {
                p = Positions.BOTTOM_CENTER;
                break;
            }
            case 4: {
                p = Positions.BOTTOM_LEFT;
                break;
            }
            case 5: {
                p = Positions.BOTTOM_RIGHT;
                break;
            }
            case 6: {
                p = Positions.TOP_CENTER;
                break;
            }
            case 7: {
                p = Positions.TOP_LEFT;
                break;
            }
            case 8: {
                p = Positions.TOP_RIGHT;
                break;
            }
            default: {
                p = Positions.CENTER;
                break;
            }
        }
        return p;
    }

    public static void main(String[] args) throws Exception {
        thumbImage("d:/pdf/1.jpg", 600, 600, "d:/pdf/2.jpg");
        crop("d:/pdf/1.jpg", 7, 200, 300, "d:/pdf/2.jpg");
        watermark("d:/pdf/1.jpg", "d:/pdf/2.jpg", 7, 1, "d:/pdf/3.jpg");
    }
}
View Code

  c)實現數據填充PDF模板orm

package com.yangwj.demo.controller;

import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;

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

/**
 * Description: PdfUtils <br>
 * 依賴的包:itextpdf    itext-asian
 * commons-io,commons-codec
 * @author mk
 * @Date 2018-11-2 14:32 <br>
 * @Param
 * @return
 */
public class PdfUtils {


    public static void main(String[] args) throws IOException {
        HashMap map = new HashMap<String, String>();
        map.put("name","楊傑");
        map.put("sex","");
        map.put("age","27");
        map.put("phone","15521331");
        map.put("email","812406fdf@qq.com");
        map.put("idCard","4305223243434332");
        map.put("hobby","跑步");
        map.put("time","2019年5月22日");
//        String path = PdfUtils.class.getResource("/template").getPath();
//        System.out.println("path:"+path);
//        String sourceFile = path + File.separator + "test.pdf";
        String sourceFile = "C:\\Users\\yangwj\\Desktop\\test.pdf";
        String targetFile = "C:\\Users\\yangwj\\Desktop\\test_fill.pdf";
       genPdf(map,sourceFile,targetFile);

//        System.out.println("獲取pdf表單中的fieldNames:"+getTemplateFileFieldNames(sourceFile));
//        System.out.println("讀取文件數組:"+fileBuff(sourceFile));
//        System.out.println("pdf轉圖片:"+pdf2Img(new File(targetFile),imageFilePath));
    }

    private static void genPdf(HashMap map, String sourceFile, String targetFile) throws IOException {
        File templateFile = new File(sourceFile);
        fillParam(map, FileUtils.readFileToByteArray(templateFile), targetFile);
    }

    /**
     * Description: 使用map中的參數填充pdf,map中的key和pdf表單中的field對應 <br>
     * @author mk
     * @Date 2018-11-2 15:21 <br>
     * @Param
     * @return
     */
    public static void fillParam(Map<String, String> fieldValueMap, byte[] file, String contractFileName) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(contractFileName);
            PdfReader reader = null;
            PdfStamper stamper = null;
            BaseFont base = null;
            try {
                reader = new PdfReader(file);
                stamper = new PdfStamper(reader, fos);
                stamper.setFormFlattening(true);
                base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                AcroFields acroFields = stamper.getAcroFields();
                for (String key : acroFields.getFields().keySet()) {
                    acroFields.setFieldProperty(key, "textfont", base, null);
                    acroFields.setFieldProperty(key, "textsize", new Float(9), null);
                }
                if (fieldValueMap != null) {
                    for (String fieldName : fieldValueMap.keySet()) {
                        acroFields.setField(fieldName, fieldValueMap.get(fieldName));
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (stamper != null) {
                    try {
                        stamper.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                if (reader != null) {
                    reader.close();
                }
            }

        } catch (Exception e) {
            System.out.println("填充參數異常");
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fos);
        }
    }

    /**
     * Description: 獲取pdf表單中的fieldNames<br>
     * @author mk
     * @Date 2018-11-2 15:21 <br>
     * @Param
     * @return
     */
    public static Set<String> getTemplateFileFieldNames(String pdfFileName) {
        Set<String> fieldNames = new TreeSet<String>();
        PdfReader reader = null;
        try {
            reader = new PdfReader(pdfFileName);
            Set<String> keys = reader.getAcroFields().getFields().keySet();
            for (String key : keys) {
                int lastIndexOf = key.lastIndexOf(".");
                int lastIndexOf2 = key.lastIndexOf("[");
                fieldNames.add(key.substring(lastIndexOf != -1 ? lastIndexOf + 1 : 0, lastIndexOf2 != -1 ? lastIndexOf2 : key.length()));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                reader.close();
            }
        }

        return fieldNames;
    }


    /**
     * Description: 讀取文件數組<br>
     * @author mk
     * @Date 2018-11-2 15:21 <br>
     * @Param
     * @return
     */
    public static byte[] fileBuff(String filePath) throws IOException {
        File file = new File(filePath);
        long fileSize = file.length();
        if (fileSize > Integer.MAX_VALUE) {
            //System.out.println("file too big...");
            return null;
        }
        FileInputStream fi = new FileInputStream(file);
        byte[] file_buff = new byte[(int) fileSize];
        int offset = 0;
        int numRead = 0;
        while (offset < file_buff.length && (numRead = fi.read(file_buff, offset, file_buff.length - offset)) >= 0) {
            offset += numRead;
        }
        // 確保全部數據均被讀取
        if (offset != file_buff.length) {
            throw new IOException("Could not completely read file " + file.getName());
        }
        fi.close();
        return file_buff;
    }

    /**
     * Description: 合併pdf <br>
     * @author mk
     * @Date 2018-11-2 15:21 <br>
     * @Param
     * @return
     */
    public static void mergePdfFiles(String[] files, String savepath) {
        Document document = null;
        try {
            document = new Document(); //默認A4大小
            PdfCopy copy = new PdfCopy(document, new FileOutputStream(savepath));
            document.open();
            for (int i = 0; i < files.length; i++) {
                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);
                    }
                } finally {
                    if (reader != null) {
                        reader.close();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //關閉PDF文檔流,OutputStream文件輸出流也將在PDF文檔流關閉方法內部關閉
            if (document != null) {
                document.close();
            }

        }
    }



    /**
     * pdf轉圖片
     * @param file pdf
     * @return
     */
    public static boolean pdf2Img(File file,String imageFilePath) {
        try {
            //生成圖片保存
            byte[] data = pdfToPic(PDDocument.load(file));
            File imageFile = new File(imageFilePath);
            ImageThumbUtils.thumbImage(data, 1, imageFilePath); //按比例壓縮圖片
            System.out.println("pdf轉圖片文件地址:" + imageFilePath);
            return true;
        } catch (Exception e) {
            System.out.println("pdf轉圖片異常:");
            e.printStackTrace();
        }

        return false;
    }

    /**
     * pdf轉圖片
     */
    private static byte[] pdfToPic(PDDocument pdDocument) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        List<BufferedImage> piclist = new ArrayList<BufferedImage>();
        try {
            PDFRenderer renderer = new PDFRenderer(pdDocument);
            for (int i = 0; i < pdDocument.getNumberOfPages(); i++) {//
                // 0 表示第一頁,300 表示轉換 dpi,越大轉換後越清晰,相對轉換速度越慢
                BufferedImage image = renderer.renderImageWithDPI(i, 108);
                piclist.add(image);
            }
            // 總高度 總寬度 臨時的高度 , 或保存偏移高度 臨時的高度,主要保存每一個高度
            int height = 0, width = 0, _height = 0, __height = 0,
                    // 圖片的數量
                    picNum = piclist.size();
            // 保存每一個文件的高度
            int[] heightArray = new int[picNum];
            // 保存圖片流
            BufferedImage buffer = null;
            // 保存全部的圖片的RGB
            List<int[]> imgRGB = new ArrayList<int[]>();
            // 保存一張圖片中的RGB數據
            int[] _imgRGB;
            for (int i = 0; i < picNum; i++) {
                buffer = piclist.get(i);
                heightArray[i] = _height = buffer.getHeight();// 圖片高度
                if (i == 0) {
                    // 圖片寬度
                    width = buffer.getWidth();
                }
                // 獲取總高度
                height += _height;
                // 從圖片中讀取RGB
                _imgRGB = new int[width * _height];
                _imgRGB = buffer.getRGB(0, 0, width, _height, _imgRGB, 0, width);
                imgRGB.add(_imgRGB);
            }

            // 設置偏移高度爲0
            _height = 0;
            // 生成新圖片
            BufferedImage imageResult = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            int[] lineRGB = new int[8 * width];
            int c = new Color(128, 128, 128).getRGB();
            for (int i = 0; i < lineRGB.length; i++) {
                lineRGB[i] = c;
            }
            for (int i = 0; i < picNum; i++) {
                __height = heightArray[i];
                // 計算偏移高度
                if (i != 0)
                    _height += __height;
                imageResult.setRGB(0, _height, width, __height, imgRGB.get(i), 0, width); // 寫入流中

                // 模擬頁分隔
                if (i > 0) {
                    imageResult.setRGB(0, _height + 2, width, 8, lineRGB, 0, width);
                }
            }
            // 寫流
            ImageIO.write(imageResult, "jpg", baos);
        } catch (Exception e) {
            System.out.println("pdf轉圖片異常:");
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(baos);
            try {
                pdDocument.close();
            } catch (Exception ignore) {
            }
        }

        return baos.toByteArray();
    }
}
View Code

 四、針對複選框的填充blog

只須要在相應的字段(現金付費)設置值爲"On"。

五、針對屬性值太長,能夠對填充框進行換行

相關文章
相關標籤/搜索