最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java中pdf模版填充表單踩坑實戰(zhàn)記錄(itextPdf、openPdf、pdfbox)

 更新時間:2025年07月29日 11:02:17   作者:代碼萌新知  
這篇文章主要介紹了java中pdf模版填充表單踩坑的相關(guān)資料,OpenPDF、iText、PDFBox是三種常用的 PDF 處理庫,它們各自具有獨特的優(yōu)勢和特點,同時也存在一些局限性和差異,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

準(zhǔn)備Pdf模版

Adobe Acrobat Dc打開pdf模版,點擊準(zhǔn)備表單出現(xiàn)自動識別的表單域,如果需要自定義表單域可點擊頂欄標(biāo)記位置自定義表單位置。

雙擊表單域,出現(xiàn)表單設(shè)置框,可設(shè)置表單字段名稱(與代碼相關(guān)),位置、以及外觀字體以及大小等(默認(rèn)值),最后點擊保存

方法1:itextpdf7填充表單

(1)加入依賴

<dependency>
   <groupId>com.itextpdf</groupId>
   <artifactId>itext7-core</artifactId>
   <version>7.1.19</version>
   <type>pom</type>
</dependency>
<dependency>
   <groupId>com.itextpdf</groupId>
   <artifactId>itext-asian</artifactId>
   <version>5.2.0</version>
</dependency>
   <groupId>com.itextpdf</groupId>
   <artifactId>font-asian</artifactId>
   <version>7.1.19</version>
   <scope>pom</scope>
</dependency>

(2)代碼

public void exportContractPdf(EnterpriseInfoVo params, HttpServletResponse response) {
       String inputFileName = "template/test.pdf";//模版路徑
       ByteArrayOutputStream baos = new ByteArrayOutputStream();
       ClassPathResource classPathResource = new ClassPathResource(inputFileName);
       try (InputStream inputStream = classPathResource.getInputStream();PdfReader reader = new PdfReader(inputStream);
           PdfWriter writer = new PdfWriter(baos);
           PdfDocument pdfDoc = new PdfDocument(reader, writer)) {
           PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);
           ClassPathResource fontResource = new ClassPathResource("ttf/STSong.ttf"); //字體路徑
           InputStream fontStream = fontResource.getInputStream();
           ByteArrayOutputStream buffer = new ByteArrayOutputStream();
           byte[] data1= new byte[1024];
           int nRead;
           while ((nRead = fontStream.read(data1, 0, data1.length)) != -1) {
               buffer.write(data1, 0, nRead);
           }
           buffer.flush();
           byte[] fontBytes = buffer.toByteArray();
           PdfFont font = PdfFontFactory.createFont(
                   fontBytes,
                   PdfEncodings.IDENTITY_H,
                   true
           );
           form.getFormFields().values().forEach(field -> field.setFont(font));
           Map<String, Object> data = new HashMap<>();
           data.put("param1", params.getParam1());
           data.put("param2",params.getParam2());
           for (Map.Entry<String, Object> entry : data.entrySet()) {
               PdfFormField field = form.getField(entry.getKey());
               if (field != null) {
                   field.setValue(entry.getValue().toString());
               }
           }
           form.flattenFields();
           pdfDoc.close();
            response.setContentType("application/pdf");
       response.setHeader("Content-Disposition", "attachment; filename=" +
               Optional.ofNullable(enterpriseInfoVo.getContract_id())
                       .orElse(URLEncoder.encode(enterpriseInfoVo.getFirm_name(), StandardCharsets.UTF_8.name())) + ".pdf");
       response.getOutputStream().write(baos.toByteArray());

       } catch (Exception e) {
           //異常處理
       }

   }

(3)遇到的問題

本來這個方法沒有任何問題,但是 由于突然要將系統(tǒng)遷移到另一個服務(wù)器,部署上去后 PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);
這行報錯 com/itextpdf/io/font/cmap/UniJIS-UTF16-H was not found.該路徑下沒有這文件但是font-asian有這個文件,本地運行正常,按照網(wǎng)上的方法加入itext-asian依賴,或者自己導(dǎo)入resource資源都試過了,還是不行。研究了很久正式服就是走不通,但是之前服務(wù)器的正式服能就走,搗鼓很久一無所獲,所以決定換方法2。

方法2:pdfbox填充表單

(1)加入依賴

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

(2)代碼

public void exportContractPdf( EnterpriseInfoVo params, HttpServletResponse response) throws ParseException {
   String inputFileName = "template/test.pdf";
   try (PDDocument document = PDDocument.load(new ClassPathResource(inputFileName).getInputStream());
        ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
       PDAcroForm form = document.getDocumentCatalog().getAcroForm();
       InputStream fontStream = new ClassPathResource("ttf/STSong.ttf").getInputStream();
       PDType0Font font = PDType0Font.load(document, fontStream, false);
       PDResources resources = new PDResources();
       resources.put(COSName.getPDFName("F1"), font);
       form.setDefaultResources(resources);
       Map<String, Object> data = new HashMap<>();
       data.put("param1", params.getParam1());
       data.put("param2", params.getParam2());
       for (PDField field : form.getFields()) {
           if (data.containsKey(field.getFullyQualifiedName())) {
               if (field instanceof PDTextField) { 
                   PDTextField textField = (PDTextField) field;
                   textField.setDefaultAppearance("/F1 10 Tf 0 g");  // 可能導(dǎo)致文件過大
                   String fullyQualifiedName = field.getFullyQualifiedName();
                   Object o = data.get(fullyQualifiedName);
                   textField.setValue(o.toString()); // 設(shè)置字段值
                   textField.setReadOnly(true); // 將字段設(shè)置為只讀
               }
           }
       }
       form.flatten();
       document.save(baos);
        response.setContentType("application/pdf");
           response.setHeader("Content-Disposition", "attachment; filename=" +
                   Optional.ofNullable(params.getId())
                           .orElse(URLEncoder.encode(enterpriseInfoVo.getName(), StandardCharsets.UTF_8.name())) + ".pdf");
           response.getOutputStream().write(baos.toByteArray());

   } catch (Exception e) {
       //異常處理
   }

}

(3)遇到的問題

由于業(yè)務(wù)需要下載協(xié)議和預(yù)覽協(xié)議,移動端在線預(yù)覽和下載時出現(xiàn)亂碼情況,暫時沒有解決問題。于是又試了方法3。

方法3:openpdf填充表單

(1)加入依賴

<dependency>
  <groupId>com.github.librepdf</groupId>
  <artifactId>openpdf</artifactId>
   <version>1.3.26</version>
</dependency>

(2)代碼

public void exportContractPdf(EnterpriseInfoVo params, HttpServletResponse response) throws ParseException {
       String inputFileName = "template/test.pdf";
       try (InputStream templateStream = new ClassPathResource(inputFileName).getInputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
           com.lowagie.text.pdf.PdfReader reader = new com.lowagie.text.pdf.PdfReader(templateStream);
           PdfStamper stamper = new PdfStamper(reader, baos);
           AcroFields form = stamper.getAcroFields();
           BaseFont font = BaseFont.createFont(
                   new ClassPathResource("ttf/STSong.ttf").getPath(),
                   BaseFont.IDENTITY_H,
                   BaseFont.EMBEDDED
           );
           Map<String, Object> data = new HashMap<>();
           data.put("param1", params.getParam1());
            data.put("param2", params.getParam2());  
           for (Object fieldName : form.getFields().keySet()) {
               if (data.containsKey(fieldName.toString())) {
                   form.addSubstitutionFont(font);               
//                    form.setFieldProperty(fieldName.toString(), "textfont", font, null); //這兩行代碼加入后直接從200k激增到7.5M
//                    form.setFieldProperty(fieldName.toString(),"textsize",Float.valueOf(10f),null);
                   Object value = data.get(fieldName);
                   form.setField(fieldName.toString(), value.toString());
                   form.setFieldProperty(fieldName.toString(), "setfflags", PdfFormField.FF_READ_ONLY, null);
               }
           }
           stamper.setFormFlattening(true);
           stamper.close();
           reader.close();
           response.setContentType("application/pdf");
           response.setHeader("Content-Disposition", "attachment; filename=" +
                   Optional.ofNullable(params.getId())
                           .orElse(URLEncoder.encode(params.getName(), StandardCharsets.UTF_8.name())) + ".pdf");
           response.getOutputStream().write(baos.toByteArray());

       } catch (Exception e) {
           //異常處理
       }
   }

(3)遇到的問題

剛開始導(dǎo)出模版出現(xiàn)填充文字大小不一,字體樣式不統(tǒng)一的情況,所以使用了//                    form.setFieldProperty(fieldName.toString(), "textfont", font, null); //這兩行代碼加入后直接從200k激增到7.5M
//                    form.setFieldProperty(fieldName.toString(),"textsize",Float.valueOf(10f),null);這兩行代碼的加入直接導(dǎo)致一頁的pdf文件從200k到7.5M,查找原因說是字體文件重復(fù)嵌入,試了很多方法總是出現(xiàn)這樣那樣的問題,所以到方法4。

方法4:itextpdf5填充表單

(1)加入依賴

<dependency>
   <groupId>com.itextpdf</groupId>
   <artifactId>itextpdf</artifactId>
   <version>5.5.13.2</version>
</dependency>
<dependency>
   <groupId>com.itextpdf.tool</groupId>
   <artifactId>xmlworker</artifactId>
   <version>5.5.13.2</version>
</dependency>
<dependency>
   <groupId>com.itextpdf</groupId>
   <artifactId>itext-asian</artifactId>
   <version>5.2.0</version>
</dependency>

<dependency>
   <groupId>wiki.xsx</groupId>
   <artifactId>x-easypdf-pdfbox</artifactId>
   <version>2.11.6</version>
</dependency>

<dependency>
   <groupId>org.xhtmlrenderer</groupId>
   <artifactId>flying-saucer-pdf-itext5</artifactId>
   <version>9.1.22</version>
   <exclusions>
       <exclusion>
           <artifactId>itextpdf</artifactId>
           <groupId>com.itextpdf</groupId>
       </exclusion>
   </exclusions>
</dependency>

(2)代碼

   public void exportContractPdf(EnterpriseInfoVo params, HttpServletResponse response) {
        String inputFileName = "template/test.pdf";
             try {     
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", "attachment; filename=" +
                    Optional.ofNullable(params.getId())
                            .orElse(URLEncoder.encode(params.getName(), StandardCharsets.UTF_8.name())) + ".pdf");
            Map<String, String> data = new HashMap<>();
            data.put("param1", params.getParam1());
            data.put("param2", params.getParam2());      
            XEasyPdfHandler.Document
                    .load( new ClassPathResource(inputFileName).getInputStream())
                    .formFiller()
                    .setFontPath(getTempFontPath("ttf/STSong.ttf"))
                    .enableCompress()
                    .enableFixForm()
                    .enableReadOnly()
                    .fill(data)
                    .finish(response.getOutputStream());

        } catch (Exception e) {
           //異常處理
        }
    }

(3)遇到的問題

剛開始出現(xiàn).fill(data)這里報空指針異常,但是data里每個都有值,針對每個值一一排查發(fā)現(xiàn)竟然有的值能填充成功有的值不行,一次排查后發(fā)現(xiàn)跟模版的表單有問題,最終針對pdf模版的表單域刪除重新創(chuàng)建就可以了。但是上線到測試服后才發(fā)現(xiàn)又有問題聯(lián)想瀏覽器預(yù)覽的pdf表單填的都是空值,下載又可以了。我不死心又拿著新建表單域的pdf模板去試方法2和方法3發(fā)現(xiàn)兩個方法的毛病解決了,所以最終我使用的方法2。至于方法1和方法4的問題實在沒有時間來驗證和排查了。

總結(jié)

到此這篇關(guān)于java中pdf模版填充表單踩坑實戰(zhàn)的文章就介紹到這了,更多相關(guān)java pdf模版填充表單內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis-Spring連接mysql 8.0配置步驟出錯的解決方法

    Mybatis-Spring連接mysql 8.0配置步驟出錯的解決方法

    這篇文章主要為大家詳細(xì)介紹了Mybatis-Spring連接mysql 8.0配置步驟出錯的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • 利用Java查看進(jìn)程內(nèi)存占用情況的實現(xiàn)方法

    利用Java查看進(jìn)程內(nèi)存占用情況的實現(xiàn)方法

    在系統(tǒng)監(jiān)控和性能調(diào)優(yōu)中,了解各個進(jìn)程的內(nèi)存占用情況是非常重要的一環(huán),通過查看進(jìn)程內(nèi)存使用情況,開發(fā)者和運維人員可以及時發(fā)現(xiàn)異常進(jìn)程、資源瓶頸和內(nèi)存泄漏問題,本項目旨在使用 Java 編寫一個簡單的程序,通過調(diào)用操作系統(tǒng)的命令來獲取系統(tǒng)中各個進(jìn)程的內(nèi)存使用情況
    2025-03-03
  • 持久層ORM框架Hibernate框架的使用及搭建方式

    持久層ORM框架Hibernate框架的使用及搭建方式

    Hibernate是一個開放源代碼的對象關(guān)系映射框架,它對JDBC進(jìn)行了非常輕量級的對象封裝,使得Java程序員可以隨心所欲的使用對象編程思維來操縱數(shù)據(jù)庫,本文重點給大家介紹持久層ORM框架Hibernate框架的使用及搭建方式,感興趣的朋友一起看看吧
    2021-11-11
  • Java實現(xiàn)簡單控制臺版ATM系統(tǒng)

    Java實現(xiàn)簡單控制臺版ATM系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)簡單控制臺版ATM系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 淺談Apache Maven ToolChains的使用

    淺談Apache Maven ToolChains的使用

    Maven是java中非常有用和常用的構(gòu)建工具,基本上現(xiàn)在大型的java項目都是Maven和gradle的天下了。本文將介紹Apache Maven ToolChains的使用。
    2021-06-06
  • Java中調(diào)用DLL動態(tài)庫的操作方法

    Java中調(diào)用DLL動態(tài)庫的操作方法

    在Java編程中,有時我們需要調(diào)用本地代碼庫,特別是Windows平臺上的DLL(動態(tài)鏈接庫),本文中,我們將詳細(xì)討論如何在Java中加載和調(diào)用DLL動態(tài)庫,并通過具體示例來展示這個過程,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • 探討java深拷貝

    探討java深拷貝

    這篇文章主要針對java深拷貝的相關(guān)內(nèi)容進(jìn)行解析,幫助大家學(xué)習(xí)理解java深拷貝,感興趣的小伙伴們可以參考一下
    2016-02-02
  • Java基礎(chǔ)之堆內(nèi)存溢出的解決

    Java基礎(chǔ)之堆內(nèi)存溢出的解決

    這篇文章主要介紹了Java基礎(chǔ)之堆內(nèi)存溢出的解決,文中有非常詳細(xì)的圖文示例及代碼示例,對正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • 詳解Java如何優(yōu)雅的使用策略模式

    詳解Java如何優(yōu)雅的使用策略模式

    設(shè)計模式是軟件設(shè)計中常見問題的典型解決方案。 它們就像能根據(jù)需求進(jìn)行調(diào)整的預(yù)制藍(lán)圖, 可用于解決代碼中反復(fù)出現(xiàn)的設(shè)計問題。今天就拿其中一個問題來分析如何優(yōu)雅的使用策略模式吧
    2023-02-02
  • Java?21使用JJWT?0.13.0的最新正確用法示例

    Java?21使用JJWT?0.13.0的最新正確用法示例

    JJWT(Java JWT)是Java平臺上相當(dāng)流行的用于生成Json Web Token的庫,其更新速度非常快,導(dǎo)致網(wǎng)上許多教程在如今看來都已經(jīng)過時,這篇文章主要介紹了Java?21使用JJWT?0.13.0的最新正確用法,需要的朋友可以參考下
    2026-04-04

最新評論

泰和县| 三河市| 兰西县| 郑州市| 谷城县| 百色市| 济南市| 凌海市| 东乌珠穆沁旗| 枝江市| 商水县| 万源市| 尤溪县| 金阳县| 普兰店市| 泾川县| 宁陵县| 陕西省| 莒南县| 浮梁县| 老河口市| 阿克苏市| 阿克| 乾安县| 西畴县| 剑阁县| 上林县| 昌乐县| 城市| 吉安县| 寻乌县| 思南县| 聊城市| 沛县| 临江市| 深水埗区| 九台市| 凤凰县| 兰溪市| 久治县| 衡东县|