Adobe Acrobat DC を使用して pdf テンプレートを作成した後、java を使用してローカルの指定されたパスに直接 pdf を生成するか、pdf ファイルをエクスポートします。

参考記事出典:
springboot+itextpdf テンプレートに従ってPDFファイルを生成し、オンラインでPDFファイルをダウンロード
JAVAはテンプレートに従ってPDFファイルを生成し、エクスポートします

Java は、指定された長さに従って文字列を文字列配列に分割します。

私の命を救ってくれた上記のブロガーに感謝します~~~

私のシステム環境: win10, IDEA, jdk1.8

1.Adobe Acrobat DCのダウンロード

Baidu リンク: リンク: https://pan.baidu.com/s/1RSV8D6kXDbWeV2owgw2Zyg
抽出コード: f8p8
は自分で取得できます。

2. テンプレートの準備

1. Word でテンプレートを描画し、pdf として保存します。

私が生成した pdf テンプレートを下の画像に示します。
PDFテンプレート

2. ソフトウェアを開きます: Adob​​e Acrobat DC

ページは下図のとおりで、[ツール] - [フォームの準備] を選択し
ここに画像の説明を挿入
、ここに上記の pdf ファイルを配置して、
ここに画像の説明を挿入
フォームの編集ページに入り、フィールドを編集します (フィールド名は、プログラム内のフィールド名と一致している必要があります)。 . 私の編集は下の写真に示されています。
ここに画像の説明を挿入
[備考]欄は下線が必要で、コメント文が少し長くなるかもしれないので、ここではこのように設定しましたが、私の考えは次のとおりです
。 、bz-line2、bz-line3 の 3 つのテキスト ドメインを作成し、それぞれの属性を設定します (ドメインをダブルクリックするだけで、テキスト サイズ、スタイルなどを設定できます)。2.プログラムでは
ここに画像の説明を挿入
、データ (文字列型) を読み込み、固定長に従って文字列をインターセプトし、bz-line1、bz-line2、bz-line3 に循環的に配置します。プログラムの後半で、私が使用するばかげた方法を示します。. . .

3. 実は。. 下線が不要な場合は、[プロパティ] の [複数行] に直接チェックを入れることで、複数テキストの改行を実現できます。
ここに画像の説明を挿入
3. 編集したテンプレートを保存する

三、Java実装

1. Maven の依存関係を追加する

          <!-- PDF工具类 -->
		  <dependency>
		      <groupId>com.itextpdf</groupId>
		      <artifactId>itextpdf</artifactId>
		      <version>5.5.13</version>
		  </dependency>
		  <!-- PDF中文支持 -->
		  <dependency>
		      <groupId>com.itextpdf</groupId>
		      <artifactId>itext-asian</artifactId>
		      <version>5.2.0</version>
		  </dependency>

2.ローカルで指定されたパスにpdfを直接生成します

(1)、pdfUtils クラス

public class PdfUtils {
    
    

    private final static Logger log = LoggerFactory.getLogger(PdfUtils.class);

    // 利用模板生成pdf,这将直接保存到指定路径
    public static void pdfout(Map<String,Object> o,String templatePath,String newPDFPath) {
    
    

        PdfReader reader;
        FileOutputStream out=null;
        ByteArrayOutputStream bos=null;
        PdfStamper stamper;
        try {
    
    
        	//系统字体
            String prefixFont = "";
            String os = System.getProperties().getProperty("os.name");
            if (os.startsWith("win") || os.startsWith("Win")) {
    
    
                prefixFont = "C:\\Windows\\Fonts" + File.separator;
            } else {
    
    
                prefixFont = "/usr/share/fonts/chinese" + File.separator;
            }
            //必须加“,0”或“,1”,否则会报错:com.itextpdf.text.DocumentException: Font 'C:\Windows\Fonts\simsun.ttc' with 'Identity-H' is not recognized.
            BaseFont bf = BaseFont.createFont(prefixFont + "simsun.ttc,0" , BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

            out = new FileOutputStream(newPDFPath);// 输出流
            reader = new PdfReader(templatePath);// 读取pdf模板
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            //文字类的内容处理
            Map<String,String> datemap = (Map<String,String>)o.get("datemap");
            form.addSubstitutionFont(bf);
            for(String key : datemap.keySet()){
    
    
                //为了文字可以有下划线,并且换行,控制每行字数,当字数超过时,将剩余文字填充至下一备选域
                if ("hzbz".equals(key)){
    
    
                    String hzbz = datemap.get(key);
                    String[] hzbzArray = stringToStringArray(hzbz,24);

                    for(int i = 0; i < hzbzArray.length; i++){
    
    
                        String fkey = "hzbz-line" + (i+1);
                        form.setField(fkey,hzbzArray[i]);
                    }

                }else if("bz".equals(key)){
    
    

                    String bz = datemap.get(key);
                    String[] bzArray = stringToStringArray(bz,24);

                    for(int i = 0; i < bzArray.length; i++){
    
    
                        String fkey = "bz-line" + (i+1);
                        form.setField(fkey,bzArray[i]);
                    }

                }else{
    
    
                    String value = datemap.get(key);
                    form.setField(key,value);
                }

            }
            //图片类的内容处理
            Map<String, Image> imgmap = (Map<String,Image>)o.get("imgmap");
            for(String key : imgmap.keySet()) {
    
    
                Image value = imgmap.get(key);
                //String imgpath = value;
                Image image = value;
                int pageNo = form.getFieldPositions(key).get(0).page;
                Rectangle signRect = form.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //根据路径读取图片
                //Image image = Image.getInstance(imgpath);
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            }
            stamper.setFormFlattening(true);// 如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑
            stamper.close();
            Document doc = new Document(PageSize.A4, 50, 40, 40, 50);
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();

            //form.getTotalRevisions();
            int pages= stamper.getReader().getNumberOfPages();
            for(int i=1;i<=pages;i++){
    
    
                PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), i);
                copy.addPage(importPage);
            }
            doc.close();
        } catch (IOException e) {
    
    
            log.error("pdfout",e);
        } catch (DocumentException e) {
    
    
            log.error("pdfout",e);
        }finally {
    
    
            if(out!=null){
    
    
                try{
    
    
                    out.close();
                }catch(Exception e){
    
    

                }
            }
            if(bos!=null){
    
    
                try{
    
    
                    bos.close();
                }catch(Exception e){
    
    

                }

            }

        }
    }

    // 将字符串按照指定长度分割成字符串数组
    public static String[] stringToStringArray(String src, int length) {
    
    
        //检查参数是否合法
        if (null == src || src.equals("")) {
    
    
            return null;
        }

        if (length <= 0) {
    
    
            return null;
        }
        int n = (src.length() + length - 1) / length; //获取整个字符串可以被切割成字符子串的个数
        String[] split = new String[n];
        for (int i = 0; i < n; i++) {
    
    
            if (i < (n - 1)) {
    
    
                split[i] = src.substring(i * length, (i + 1) * length);
            } else {
    
    
                split[i] = src.substring(i * length);
            }
        }
        return split;
    }

    public static  byte[] inputstream2Bytes(InputStream inStream)  throws IOException{
    
    
        byte[] in_b = null;
        try{
    
    
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100]; //buff用于存放循环读取的临时数据
            int rc = 0;
            while ((rc = inStream.read(buff, 0, 100)) > 0) {
    
    
                swapStream.write(buff, 0, rc);
            }
            in_b = swapStream.toByteArray(); //in_b为转换之后的结果

        }catch(Exception e){
    
    
            log.error("inputstream2Bytes",e);
        }finally {
    
    
            inStream.close();
        }
        return in_b;
    }

    /**
     * @Description: 文件转流
     */
    public static InputStream file2InputStream(File file)  throws IOException{
    
    
        return new FileInputStream(file);
    }

(2)、コントローラ層

@Controller
@RequestMapping("/pdf")
public class PdfController {
    
    

    @PostMapping("/createPdf")
    @ResponseBody
    public DataObject CreatePdf() throws AppException {
    
    

        //1、调用数据库,获取数据
		//此处写读取数据的代码
		
        //2、将数据存为key-value
        //存文字信息
        Map<String,String> map = new HashMap();
        //存图像信息
        Map<String,Image> mapI = new HashMap();
        map.put("name","田XX");
        map.put("sex","女");
        map.put("grbh","123456789010");
        map.put("sfzh","000000000000000000");
        map.put("rylb","啊哦");
        map.put("time1","2021-9-27");
        map.put("ddyy1","啊哦");
        map.put("time2","");
        map.put("ddyy2","");
        map.put("hzbz","有的人一生默默无闻,有的人一生轰轰烈烈,甚至千古流芳,为什么会这样?因为默默无闻的人只是满足于现状,而不去想怎么轰轰烈烈过一生,不要求自己,去做");
        map.put("bz","有的人一生默默无闻,有的人一生轰轰烈烈,甚至千古流芳,为什么会这样?因为默默无闻的人只是满足于现状,而不去想怎么轰轰烈烈过一生,不要求自己,去做");
        try{
    
    
            //图片路径
            File pic_file = new File("F:\\1555074510295049.jpg");
            Image pic_image = Image.getInstance(inputstream2Bytes(file2InputStream(pic_file)));
            mapI.put("pic",pic_image);
        }catch(Exception e){
    
    
        }

        Map<String,Object> o=new HashMap();
        o.put("datemap",map);
        o.put("imgmap",mapI);

        // 模板路径
        String templatePath = "/META-INF/resources/static/template/template.pdf";
        // 生成的新文件路径
        String newPDFPath = "F:\\template_sc.pdf";
        pdfout(o,templatePath,newPDFPath);
        return DataObject.getInstance();
    }
}

(3)正面玄関

layui.sight.ajaxRequest({
    
    
     type : 'post',
     async : true,
     url : layui.sight.compileUrl('${rc.contextPath}/pdf/CreatePdf'),
     data : [],
     callback : function(data) {
    
    
         alert("成功!")
     },
     failedCallback : function(data) {
    
    }
});

3.PDFをエクスポート

(1) pdfUtils クラス

public class PdfUtils {
    
    

    private final static Logger log = LoggerFactory.getLogger(PdfUtils.class);

    /**
     * 利用模板生成pdf导出
     */
    public static void pdfExport(Map<String, Object> o, HttpServletResponse response) {
    
    

        // 模板路径
        String templatePath = "/META-INF/resources/static/template/template.pdf";

        File file = new File(templatePath);
        if (!file.exists()) {
    
    
            try {
    
    
                file.createNewFile();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        PdfReader reader;
        ByteArrayOutputStream bos;
        PdfStamper stamper;
        OutputStream out = null;
        try {
    
    
            BaseFont bf = BaseFont.createFont("C:/Windows/Fonts/simfang.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            // 输出流
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + URLEncoder.encode("template_scsc.pdf", "UTF-8"));
            out = new BufferedOutputStream(response.getOutputStream());
            // 读取pdf模板
            reader = new PdfReader(templatePath);
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            //文字类的内容处理
            Map<String,String> datemap = (Map<String,String>)o.get("datemap");
            form.addSubstitutionFont(bf);
            for(String key : datemap.keySet()){
    
    
                //为了文字可以有下划线,并且换行,控制每行字数,当字数超过时,将剩余文字填充至下一备选域
                if ("hzbz".equals(key)){
    
    
                    String hzbz = datemap.get(key);
                    String[] hzbzArray = stringToStringArray(hzbz,24);

                    for(int i = 0; i < hzbzArray.length; i++){
    
    
                        String fkey = "hzbz-line" + (i+1);
                        form.setField(fkey,hzbzArray[i]);
                    }

                }else if("bz".equals(key)){
    
    

                    String bz = datemap.get(key);
                    String[] bzArray = stringToStringArray(bz,24);

                    for(int i = 0; i < bzArray.length; i++){
    
    
                        String fkey = "bz-line" + (i+1);
                        form.setField(fkey,bzArray[i]);
                    }

                }else{
    
    
                    String value = datemap.get(key);
                    form.setField(key,value);
                }

            }
            //图片类的内容处理
            Map<String, Image> imgmap = (Map<String,Image>)o.get("imgmap");
            for(String key : imgmap.keySet()) {
    
    
                Image value = imgmap.get(key);
                //String imgpath = value;
                Image image = value;
                int pageNo = form.getFieldPositions(key).get(0).page;
                Rectangle signRect = form.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //根据路径读取图片
                //Image image = Image.getInstance(imgpath);
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            }
            stamper.setFormFlattening(true);
            stamper.close();
            Document doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            copy.addPage(importPage);
            doc.close();

        } catch (IOException | DocumentException e) {
    
    
            System.out.println(e);
        } finally {
    
    
            try {
    
    
                assert out != null;
                out.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
    }

    // 将字符串按照指定长度分割成字符串数组
    public static String[] stringToStringArray(String src, int length) {
    
    
        //检查参数是否合法
        if (null == src || src.equals("")) {
    
    
            return null;
        }

        if (length <= 0) {
    
    
            return null;
        }
        int n = (src.length() + length - 1) / length; //获取整个字符串可以被切割成字符子串的个数
        String[] split = new String[n];
        for (int i = 0; i < n; i++) {
    
    
            if (i < (n - 1)) {
    
    
                split[i] = src.substring(i * length, (i + 1) * length);
            } else {
    
    
                split[i] = src.substring(i * length);
            }
        }
        return split;
    }

    public static  byte[] inputstream2Bytes(InputStream inStream)  throws IOException{
    
    
        byte[] in_b = null;
        try{
    
    
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100]; //buff用于存放循环读取的临时数据
            int rc = 0;
            while ((rc = inStream.read(buff, 0, 100)) > 0) {
    
    
                swapStream.write(buff, 0, rc);
            }
            in_b = swapStream.toByteArray(); //in_b为转换之后的结果

        }catch(Exception e){
    
    
            log.error("inputstream2Bytes",e);
        }finally {
    
    
            inStream.close();
        }
        return in_b;
    }

    /**
     * @Description: 文件转流
     */
    public static InputStream file2InputStream(File file)  throws IOException{
    
    
        return new FileInputStream(file);
    }

(2)、コントローラ層

@Controller
@RequestMapping("/pdf")
public class PdfController {
    
    

    @RequestMapping("/exportPdf")
    public void exportPdf(HttpServletRequest request, HttpServletResponse response) throws AppException {
    
    
        
        //调用数据库,获取数据

        //将数据存为key-value
        //存文字信息
        Map<String,String> map = new HashMap();
        //存图像信息
        Map<String,Image> mapI = new HashMap();
        map.put("name","田XX");
        map.put("sex","女");
        map.put("grbh","12345678910");
        map.put("sfzh","00000000000000000");
        map.put("rylb","啊哦");
        map.put("time1","2021-9-27");
        map.put("ddyy1","啊哦");
        map.put("time2","");
        map.put("ddyy2","");
        map.put("hzbz","有的人一生默默无闻,有的人一生轰轰烈烈,甚至千古流芳,为什么会这样?因为默默无闻的人只是满足于现状,而不去想怎么轰轰烈烈过一生,不要求自己,去做");
        map.put("bz","有的人一生默默无闻,有的人一生轰轰烈烈,甚至千古流芳,为什么会这样?因为默默无闻的人只是满足于现状,而不去想怎么轰轰烈烈过一生,不要求自己,去做");
        try{
    
    
            //图片路径
            File pic_file = new File("F:\\1555074510295049.jpg");
            Image pic_image = Image.getInstance(inputstream2Bytes(file2InputStream(pic_file)));
            mapI.put("pic",pic_image);
        }catch(Exception e){
    
    
        }

        Map<String,Object> o=new HashMap();
        o.put("datemap",map);
        o.put("imgmap",mapI);

        pdfExport(o,response);
    }
}

(3)正面玄関

function down(){
    
    
    var url = layui.sight.compileUrl('${rc.contextPath}/pdf/exportPdf');
    window.open(encodeURI(url));
}

4. 最終的な効果

ここに画像の説明を挿入
写真はうまく選択されていません。.

五、問題がある

プロジェクトがパッケージ化された後、jar パッケージが開始されたときに null ポインター エラーが報告されます.具体的なエラーの説明をコピーするのを忘れていました.

解決策: PdfUtils
を変更します変更後:

 /**
     * 利用模板生成pdf导出
     */
    public static void pdfExport(Map<String, Object> o, HttpServletResponse response) throws IOException {
    
    

        // 生成的新文件路径
        String filePath = "D:\\test.text";

        // 模板路径
        Resource resource = new ClassPathResource("/META-INF/resources/static/template/template.pdf");
        File inuModel = new File(filePath);
        FileUtils.copyInputStreamToFile(resource.getInputStream(), inuModel);


        PdfReader reader;
        ByteArrayOutputStream bos;
        PdfStamper stamper;
        OutputStream out = null;
        try {
    
    
            BaseFont bf = BaseFont.createFont("C:/Windows/Fonts/simfang.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            // 输出流
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + URLEncoder.encode("template_scsc.pdf", "UTF-8"));
            out = new BufferedOutputStream(response.getOutputStream());
            // 读取pdf模板
            reader = new PdfReader(filePath);
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            //文字类的内容处理
            Map<String,String> datemap = (Map<String,String>)o.get("datemap");
            form.addSubstitutionFont(bf);
            for(String key : datemap.keySet()){
    
    

                String value = datemap.get(key);
                form.setField(key,value);

            }
            //图片类的内容处理
            Map<String, Image> imgmap = (Map<String,Image>)o.get("imgmap");
            for(String key : imgmap.keySet()) {
    
    
                Image value = imgmap.get(key);
                //String imgpath = value;
                Image image = value;
                int pageNo = form.getFieldPositions(key).get(0).page;
                Rectangle signRect = form.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //根据路径读取图片
                //Image image = Image.getInstance(imgpath);
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            }
            stamper.setFormFlattening(true);
            stamper.close();
            Document doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            copy.addPage(importPage);
            doc.close();

        } catch (IOException | DocumentException e) {
    
    
            System.out.println(e);
        } finally {
    
    
            try {
    
    
                assert out != null;
                out.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
    }

おすすめ

転載: blog.csdn.net/qq_42622871/article/details/121516207