51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Java使用itext7生成PDF文件(三)

本文深入讨论了Java中处理PDF的实用技巧,重点介绍了使用iText 7创建PDF文档的方法,以及运用Apache PDFBox将PDF文件转换成图片的技术,同时特别关注了中文字体显示问题的解决方案。

iText 7:生成 PDF {#itext-7%EF%BC%9A%E7%94%9F%E6%88%90-pdf}

iText 7 是一个用于创建和操作 PDF 文档的开源 Java 库。它提供了丰富的功能来定制 PDF 的内容和格式。

先看下生成的pdf 和png最终效果

2023-12-29-ufaiyrhg.png

设置项目 {#%E8%AE%BE%E7%BD%AE%E9%A1%B9%E7%9B%AE}

  1. 在项目中添加 iText 7 依赖项。如果您使用 Maven,可以添加以下依赖到 pom.xml

  2. 这里我们使用当前最新版

     <!-- https://github.com/itext/itext7 -->
            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itext7-core</artifactId>
                <version>8.0.2</version>
                <type>pom</type>
            </dependency>
    

配置中文字体 {#%E9%85%8D%E7%BD%AE%E4%B8%AD%E6%96%87%E5%AD%97%E4%BD%93}

1.把字体放到resources/fonts下

2023-12-29-tspicbzn.png2. 获取字体方法

  /**
     * 获取自定义字体
     *
     * @return 自定义字体
     */
    public static PdfFont getChineseFont() {
        try {
            // 字体文件的路径
            String fontPath = "/home/wxy/Desktop/STSong-Light.ttf";
			// PdfDemo02 为当前类
            String fontPath2 = PdfDemo02.class.getResource("/fonts/classicSongSiJian.ttf").getPath();
        // 使用文件路径创建字体 并指定嵌入策略
        return PdfFontFactory.createFont(fontPath2, &quot;Identity-H&quot;,
            PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED);
    } catch (IOException e) {
        e.printStackTrace();
        System.out.println(&quot;获取中文字体失败!&quot;);
        return null;
    }
}


字体下载: https://wangxy.lanzouw.com/b02rgxskh

EmbeddingStrategy 枚举是 iText 7 中 PdfFontFactory.createFont 方法的一部分,在这个枚举中,FORCE_EMBEDDED 和 PREFER_EMBEDDED 是最常用的选项,用于指定字体是否应该被嵌入到 PDF 文档中。

我们这里使用PREFER_EMBEDDED 嵌入字体,否则下文pdf生成图片时可能会中文乱码。

如果不考虑转图片,可以选择不嵌入字体,嵌入可能会稍微增大pdf文件。

绘制PDF {#%E7%BB%98%E5%88%B6pdf}

整体布局使用一个Table来布局,条码使绝对定位方式来确定位置

绝对定位时要注意:itextpdf的确定页面上的具体坐标是通过坐标来确定的。 它们的坐标轴是这样的:以左下角为原点的xy坐标轴。

2023-12-29-newkufzx.png

完整绘制方法代码

    /**
     * @param document
     */
    public static void drawBaseInfo(Document document) throws MalformedURLException {
        // 黑色虚线边框
        DeviceRgb black = new DeviceRgb(0, 0, 0);
        SolidBorder solidBorder = new SolidBorder(black, 0.5F);
    Table table = new Table(5);
    table.useAllAvailableWidth();
    table.setTextAlignment(TextAlignment.CENTER);
    table.setFont(getChineseFont());
    table.setFontSize(12);
    table.setPadding(0);
// 条码
PdfDocument pdfDocument = document.getPdfDocument();
PdfPage page = pdfDocument.addNewPage();
Barcode128 barcode128 = new Barcode128(pdfDocument);
barcode128.setCode(&amp;quot;072201130001EF&amp;quot;);
barcode128.setCodeType(Barcode128.CODE128);
barcode128.fitWidth(180);
PdfFormXObject object =
    barcode128.createFormXObject(ColorConstants.BLACK, ColorConstants.BLACK, pdfDocument);

float width = object.getWidth();
float height = object.getHeight();
float x = 200;
float y = 550;

PdfCanvas canvas = new PdfCanvas(page);
canvas.saveState();
canvas.setFillColor(ColorConstants.WHITE);
canvas.rectangle(x, y, width, height);
canvas.fill();
canvas.restoreState();
canvas.addXObjectAt(object, x, y);

// 顶部
Cell cell1 =
    new Cell(1, 8).add(
        new Paragraph(&amp;quot;客运站结算单&amp;quot;));

// cell1.setBold(); cell1.setFontSize(14); cell1.setBorder(Border.NO_BORDER);

    table.addCell(cell1);
    table.setMarginTop(20);
Cell cell2_1 =
    new Cell(1, 5).add(
        new Paragraph(&amp;quot;无三品签字:  &amp;quot;));
cell2_1.setTextAlignment(TextAlignment.RIGHT);
cell2_1.setBorder(Border.NO_BORDER);
cell2_1.setPaddingRight(80);
table.addCell(cell2_1);


Cell cell3_1 =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;乘车站:  &amp;quot;));
cell3_1.setTextAlignment(TextAlignment.RIGHT);
cell3_1.setBorder(Border.NO_BORDER);
table.addCell(cell3_1);

Cell cell3_1_v =
    new Cell(1, 2).add(
        new Paragraph(&amp;quot;中心站&amp;quot;));
cell3_1_v.setTextAlignment(TextAlignment.LEFT);
cell3_1_v.setBorder(Border.NO_BORDER);
table.addCell(cell3_1_v);

Cell cell3_2 =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;车次: &amp;quot;));
cell3_2.setTextAlignment(TextAlignment.RIGHT);
cell3_2.setBorder(Border.NO_BORDER);
table.addCell(cell3_2);

Cell cell3_2_v =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;4038&amp;quot;));
cell3_2_v.setTextAlignment(TextAlignment.LEFT);
cell3_2_v.setBorder(Border.NO_BORDER);
table.addCell(cell3_2_v);

Cell cell4_1 =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;发车时间:  &amp;quot;));
cell4_1.setTextAlignment(TextAlignment.RIGHT);
cell4_1.setBorder(Border.NO_BORDER);
table.addCell(cell4_1);

Cell cell4_1_v =
    new Cell(1, 2).add(
        new Paragraph(&amp;quot;2023-12-11 16:00&amp;quot;));
cell4_1_v.setTextAlignment(TextAlignment.LEFT);
cell4_1_v.setBorder(Border.NO_BORDER);
table.addCell(cell4_1_v);

Cell cell4_2 =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;线路:  &amp;quot;));
cell4_2.setTextAlignment(TextAlignment.RIGHT);
cell4_2.setBorder(Border.NO_BORDER);
table.addCell(cell4_2);

Cell cell4_2_v =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;卫士&amp;quot;));
cell4_2_v.setTextAlignment(TextAlignment.LEFT);
cell4_2_v.setBorder(Border.NO_BORDER);
table.addCell(cell4_2_v);


Cell cell5_1 =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;公司:  &amp;quot;));
cell5_1.setTextAlignment(TextAlignment.RIGHT);
cell5_1.setBorder(Border.NO_BORDER);
table.addCell(cell5_1);

Cell cell5_1_v =
    new Cell(1, 2).add(
        new Paragraph(&amp;quot;xxx公司&amp;quot;));
cell5_1_v.setTextAlignment(TextAlignment.LEFT);
cell5_1_v.setBorder(Border.NO_BORDER);
table.addCell(cell5_1_v);

Cell cell5_2 =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;车辆:  &amp;quot;));
cell5_2.setTextAlignment(TextAlignment.RIGHT);
cell5_2.setBorder(Border.NO_BORDER);
table.addCell(cell5_2);

Cell cell5_2_v =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;豫A99999&amp;quot;));
cell5_2_v.setTextAlignment(TextAlignment.LEFT);
cell5_2_v.setBorder(Border.NO_BORDER);
table.addCell(cell5_2_v);


Cell cell6_1 =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;单据号:  &amp;quot;));
cell6_1.setTextAlignment(TextAlignment.RIGHT);
cell6_1.setBorder(Border.NO_BORDER);
table.addCell(cell6_1);

Cell cell6_1_v =
    new Cell(1, 2).add(
        new Paragraph(&amp;quot;E36666&amp;quot;));
cell6_1_v.setTextAlignment(TextAlignment.LEFT);
cell6_1_v.setBorder(Border.NO_BORDER);
table.addCell(cell6_1_v);

Cell cell6_2 =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;核定人数:  &amp;quot;));
cell6_2.setTextAlignment(TextAlignment.RIGHT);
cell6_2.setBorder(Border.NO_BORDER);
table.addCell(cell6_2);

Cell cell6_2_v =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;9999&amp;quot;));
cell6_2_v.setTextAlignment(TextAlignment.LEFT);
cell6_2_v.setBorder(Border.NO_BORDER);
table.addCell(cell6_2_v);

Cell cell7_1 =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;内外:  &amp;quot;));
cell7_1.setTextAlignment(TextAlignment.RIGHT);
cell7_1.setBorder(Border.NO_BORDER);
table.addCell(cell7_1);

Cell cell7_1_v =
    new Cell(1, 2).add(
        new Paragraph(&amp;quot;内结&amp;quot;));
cell7_1_v.setTextAlignment(TextAlignment.LEFT);
cell7_1_v.setBorder(Border.NO_BORDER);
table.addCell(cell7_1_v);

Cell cell7_2 =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;类别:  &amp;quot;));
cell7_2.setTextAlignment(TextAlignment.RIGHT);
cell7_2.setBorder(Border.NO_BORDER);
table.addCell(cell7_2);

Cell cell7_2_v =
    new Cell(1, 1).add(
        new Paragraph(&amp;quot;正常检票&amp;quot;));
cell7_2_v.setTextAlignment(TextAlignment.LEFT);
cell7_2_v.setBorder(Border.NO_BORDER);
table.addCell(cell7_2_v);


// 第8行
List&amp;amp;lt;String&amp;amp;gt; titleList =
    Arrays.asList(&amp;quot;到站&amp;quot;, &amp;quot;票价&amp;quot;, &amp;quot;全价&amp;quot;, &amp;quot;优惠票&amp;quot;, &amp;quot;售票站&amp;quot;);
for (int i = 0; i &amp;amp;lt; 5; i++) {
    Cell cell =
        new Cell(1, 1).add(new Paragraph(titleList.get(i)));
    cell.setBorder(solidBorder);
    table.addCell(cell);
}

// 模拟数据列表
ArrayList&amp;amp;lt;Map&amp;amp;gt; dataList = new ArrayList&amp;amp;lt;&amp;amp;gt;();
for (int i = 0; i &amp;amp;lt; 6; i++) {
    HashMap&amp;amp;lt;String, String&amp;amp;gt; map = new HashMap&amp;amp;lt;&amp;amp;gt;();
    map.put(&amp;quot;到站&amp;quot;, &amp;quot;某某&amp;quot;);
    map.put(&amp;quot;票价&amp;quot;, &amp;quot;13&amp;quot;);
    map.put(&amp;quot;全价&amp;quot;, &amp;quot;1&amp;quot;);
    map.put(&amp;quot;优惠票&amp;quot;, &amp;quot;1&amp;quot;);
    map.put(&amp;quot;售票站&amp;quot;, &amp;quot;34&amp;quot;);
    dataList.add(map);
}

//   渲染数据
dataList.forEach(item -&amp;amp;gt; {
    titleList.forEach(title -&amp;amp;gt; {
        String value = String.valueOf(item.get(title));
        Cell cell =
            new Cell(1, 1).add(new Paragraph(value));
        cell.setBorder(solidBorder).setFontColor(ColorConstants.RED);
        table.addCell(cell);
    });
});


Cell cell9_1 = new Cell(1, 1).add(
    new Paragraph(&amp;quot;总人数&amp;quot;));
table.addCell(cell9_1);

Cell cell9_2 = new Cell(1, 4).add(
    new Paragraph(&amp;quot;20&amp;quot;));
table.addCell(cell9_2);


Cell cell10_1 = new Cell(1, 1).add(
    new Paragraph(&amp;quot;结算金额&amp;quot;));
table.addCell(cell10_1);

Cell cell10_2 = new Cell(1, 4).add(
    new Paragraph(&amp;quot;¥204.99&amp;quot;));
table.addCell(cell10_2);


Cell cell11_1 = new Cell(1, 1).add(
    new Paragraph(&amp;quot; &amp;quot;));
table.addCell(cell11_1);

Cell cell11_2 = new Cell(1, 4).add(
    new Paragraph(&amp;quot;xxxxxx&amp;quot;));
table.addCell(cell11_2);


Cell cell12_1 = new Cell(1, 2).add(
    new Paragraph(&amp;quot;检票员: &amp;quot;+&amp;quot;808-xxx&amp;quot;));
cell12_1.setBorder(Border.NO_BORDER);
cell12_1.setTextAlignment(TextAlignment.LEFT);
table.addCell(cell12_1);


Cell cell12_2 = new Cell(1, 3).add(
    new Paragraph(&amp;quot;打印时间: &amp;quot;+&amp;quot;2023-12-12 12:00:00&amp;quot;));
cell12_2.setTextAlignment(TextAlignment.RIGHT);
cell12_2.setBorder(Border.NO_BORDER);
table.addCell(cell12_2);

document.add(table);

}&lt;/code&gt;&lt;/pre&gt;

<br />

<br />

Apache PDFBox:PDF 转图片 {#apache-pdfbox%EF%BC%9Apdf-%E8%BD%AC%E5%9B%BE%E7%89%87}

Apache PDFBox 是另一个开源的 Java 库,用于处理 PDF 文件。它可以用于将 PDF 页面转换为图像。

设置项目 {#%E8%AE%BE%E7%BD%AE%E9%A1%B9%E7%9B%AE-1}

  1. 添加 Apache PDFBox 依赖项,我们这里也使用当前最新版:

            &lt;!-- https://github.com/apache/pdfbox  --&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;org.apache.pdfbox&lt;/groupId&gt;
                &lt;artifactId&gt;pdfbox&lt;/artifactId&gt;
                &lt;version&gt;3.0.1&lt;/version&gt;
            &lt;/dependency&gt;
    

转换为图片 {#%E8%BD%AC%E6%8D%A2%E4%B8%BA%E5%9B%BE%E7%89%87}

完整代码

 public static void pdf2Image(String PdfFilePath, String dstImgFolder, int dpi) {
        File file = new File(PdfFilePath);
    try (PDDocument pdDocument = Loader.loadPDF(new File(PdfFilePath))) {
        int dot = file.getName().lastIndexOf('.');
        String imagePDFName = file.getName().substring(0, dot); // 获取图片文件名
        PDFRenderer renderer = new PDFRenderer(pdDocument);
        /* dpi越大转换后越清晰,相对转换速度越慢 */
        int pages = 1;
        StringBuffer imgFilePath = null;
        for (int i = 0; i &amp;amp;lt; pages; i++) {
            String imgFilePathPrefix = dstImgFolder + File.separator + imagePDFName;
            imgFilePath = new StringBuffer();
            imgFilePath.append(imgFilePathPrefix);
            imgFilePath.append(&amp;quot;.png&amp;quot;);
            File dstFile = new File(imgFilePath.toString());
            BufferedImage image = renderer.renderImageWithDPI(i, dpi);
            ImageIO.write(image, &amp;quot;png&amp;quot;, dstFile);
        }
        System.out.println(&amp;quot;PDF文档转PNG图片成功!&amp;quot;);
    } catch (IOException e) {
        e.printStackTrace();
    }
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;

&lt;br /&gt;

如果pdf中文正常,转图片时图片中文乱码,可以把pdf字体策略修改为强制 EmbeddingStrategy.FORCE_EMBEDDED

&lt;br /&gt;

运行测试 {#%E8%BF%90%E8%A1%8C%E6%B5%8B%E8%AF%95}


    public static void main(String[] args) throws IOException {

        //首先你需要一个writer对象
        PdfWriter writer = new PdfWriter(&amp;quot;/home/wxy/Desktop/test.pdf&amp;quot;);
        //需要一个pdf的对象来操作pdf
        PdfDocument pdf = new PdfDocument(writer);

        //需要一个document的对象来操作数据 指定为A4大小
        try (Document document = new Document(pdf, PageSize.A5);) {
            drawBaseInfo(document);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
        pdf2Image(&amp;quot;/home/wxy/Desktop/test.pdf&amp;quot;, &amp;quot;/home/wxy/Desktop/&amp;quot;, 120);

    }&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;



 
**结语** {#%E7%BB%93%E8%AF%AD}
----------------------------


 
结合使用 iText 7 和 Apache PDFBox,您可以轻松地在 Java 应用程序中生成和操作 PDF 文件。通过适当地处理中文字体,您可以确保 PDF 文档在不同环境下都能正确显示中文内容。

 
这只是一个简单的介绍。iText 7 和 Apache PDFBox 都提供了许多高级功能,可以用于更复杂的 PDF 处理任务。探索这些功能,您可以创建更加丰富和动态的文档。

 
&amp;lt;br /&amp;gt;



 
相关文章 {#%E7%9B%B8%E5%85%B3%E6%96%87%E7%AB%A0}
--------------------------------------------


 

        
   
         https://51tbox.com/ 
  
        

 

        
   
         https://51tbox.com/ 
  
        


赞(3)
未经允许不得转载:工具盒子 » Java使用itext7生成PDF文件(三)