PDF導入導出(itextpdf)


1.導入jar

        <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>
        </dependency>            

2.導出

    //pdf template path
    private static String TEMPLATEPATH = "";
    //new pdf path
    private static String NEWPATH = "";

    /**
     * @description: pdf export
     */
    public static String exportPdfFile(String numName,Map<String,Object> objectMap,String templateName,String newName){
        // 參數轉換
        Map<String,String> map = checkPdfTemplate(numName,objectMap);
        // 生成pdf文件
        String newFilePath = pdfOut(map,"","");
        return newFilePath;
    }
    /**
     * @description: check pdf Template
     */
    public static Map<String,String> checkPdfTemplate(String numName,Map<String,Object> objectMap){
        Map<String,Object> map = new HashMap<>();
        if (numName.equals("xx")){
            map = pdfParams(objectMap);
        }
        Map<String,String> maps = map.entrySet().stream()
                .filter(e -> e.getValue() != null)
                .collect(Collectors.toMap(Map.Entry::getKey,e-> (String)e.getValue()));
        return maps;
    }
    /**
     * @description: pdf params package
     */
    public static Map<String,Object> pdfParams(Map<String,Object> objectMap){
        Map<String,Object> map = new HashMap<>();
        map.put("xxx",objectMap.get(""));
        return map;
    }
    /**
     * @description: template create pdf
     */
    public static String pdfOut(Map<String,String> params, String templateName, String newName ){
        PdfReader reader;
        FileOutputStream out;
        ByteArrayOutputStream bos;
        PdfStamper stamper;
        Document doc = null;
        try {
            BaseFont bf = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
            // 生成文件流
            out = new FileOutputStream(NEWPATH+newName);
            // 讀取pdf模板
            reader = new PdfReader(TEMPLATEPATH+templateName);
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            // 參數值轉換為formMap
            form.addSubstitutionFont(bf);
            for(String key : params.keySet()){
                String value = params.get(key);
                form.setField(key,value);
            }
            // 如果為false,生成的PDF文件可以編輯,如果為true,生成的PDF文件不可以編輯
            stamper.setFormFlattening(false);
            stamper.close();
            doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();
            PdfImportedPage importPage = null;
            // 循環復制頁面
            for (int i=1;i<=reader.getNumberOfPages();i++){
                importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), i);
                copy.addPage(importPage);
            }
            doc.close();
        }catch (Exception e){
            throw new PdfException(e);
        }finally {
            doc.close();
            return NEWPATH+newName;
        }
    }

2.1模板制作

模板使用Adobe Acrobat X Pro進行制作(下載正版工具,試用期30天,可以下載注冊機激活)

第一步,打開模板文件,沒有模板文件就創建空白文件

第二步,在Tools里面找到Forms,點擊Edit(編輯)進入的下面這個頁面

第三步,點擊Add New Field,選擇合適的工具框,文本類的一般選擇Text Field,拖拽文本框到合適的位置,雙擊編輯文本名稱(最好自己定義名稱,不要使用默認的)

 第四步,選擇File->Save as->PDF(另保存),保存完模板就可以直接使用了

   map.put("xxx",objectMap.get("")); //xxx對應Text Field的名稱,進行遍歷賦值操作

 3.導入

/**
 * @description: pdf import
 */
public static Map<String,Object> importPdfFile(MultipartFile file) throws PdfException {
    PdfReader reader = null;
    ByteArrayOutputStream bos;
    PdfStamper stamper;
    Map<String,Object> map1 = new HashMap<>();
    String con = "";
    try {
        BaseFont bf = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
        reader = new PdfReader(file.getInputStream());
        bos = new ByteArrayOutputStream();
        stamper = new PdfStamper(reader, bos);
        AcroFields form = stamper.getAcroFields();
        form.addSubstitutionFont(bf);
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        int pageNum = reader.getNumberOfPages();
        String pageContent = "";
        // 只能從第1頁開始讀
        for (int i = 1; i <= pageNum; i++) {
            PdfRenderListener listener = new PdfRenderListener();
            // 解析PDF,並處理里面的文字
            parser.processContent(i, listener);
            List<Map<String, Rectangle2D.Float>> list_text = listener.rows_text_rect;
            for (int k = 0; k < list_text.size(); k++) {
                Map<String, Rectangle2D.Float> map = list_text.get(k);
                for (Map.Entry<String, Rectangle2D.Float> entry : map.entrySet()) {
                    //每個內容和對應的坐標
                    //System.out.println(entry.getKey() + "---" + entry.getValue());
                    con += entry.getKey();
                }
            }
        }
    }catch (Exception e){
        throw new PdfException(e);
    }finally {
        reader.close();
    }
    System.out.println("con = " + con);
    return map1;
}

3.1PdfRenderListener解析規則,解析規則需要實現RenderListener接口自定義規則

public class PdfRenderListener implements RenderListener {
    /*----------------*/
    //存放文字的矩形
    public List<Rectangle2D.Float> rectText = new ArrayList<>();
    //存放文字
    public List<String> textList = new ArrayList<>();
    //存放文字的Y坐標
    public List<Float> listY = new ArrayList<>();
    //存放每一行文字的坐標位置
    public List<Map<String,Rectangle2D.Float>> rows_text_rect = new ArrayList<>();

    @Override
    public void beginTextBlock() {
      //解析之前做處理
    }
    //文字處理
    @Override
    public void renderText(TextRenderInfo textRenderInfo) {
        String text = textRenderInfo.getText();
        if (text.length() > 0){
            RectangularShape  rectBase = textRenderInfo.getBaseline().getBoundingRectange();
            //rectAsce測試和rectBase結果一樣,未發現明顯區別
    Rectangle2D.Float rectAsce = textRenderInfo.getAscentLine().getBoundingRectange();
            float leftX = (float) rectBase.getMinX();
            float leftY = (float) rectBase.getMinY();
            float rightX = (float) rectBase.getMaxX();
            float rightY = (float) rectBase.getMaxY();
            Rectangle2D.Float rect = new Rectangle2D.Float(leftX, leftY, rightX - leftX, rightY - leftY);
            if(listY.contains(rect.y)){
                int index = listY.indexOf(rect.y);
                float tempx = rect.x > rectText.get(index).x ? rectText.get(index).x : rect.x;
                rectText.set(index,new Rectangle2D.Float(tempx,rect.y,rect.width + rectText.get(index).width,rect.height));
                textList.set(index,textList.get(index) + text);
            }else{
                rectText.add(rect);
                textList.add(text);
                listY.add(rect.y);
            }
            Map<String,Rectangle2D.Float> map = new HashMap<>();
            map.put(text,rect);
            rows_text_rect.add(map);
        }
    }

    @Override
    public void endTextBlock() {
    //解析之后操作
    }

    @Override
    public void renderImage(ImageRenderInfo imageRenderInfo) {
    //解析圖片操作
    }
}        

 ps:目前獲取到的PDF文字,使用模板再次導入的情況下只能獲取到固定的文字,Field的獲取不到,Field獲取思路:1.通過坐標軸獲取,文檔不復雜還好,不然工作量很大 2.jar中工具類獲取(目前還沒找到),這塊后面有時間再研究下,后補。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM