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