使用 iText pdfHTML 的 PDF 页面大小和格式

2024-02-24

我正在尝试使用 iText7.1.0 和 pdfHTML2.0.0 将 3 个 HTML 页面(均具有相同内容)导出为 PDF这个例子 https://developers.itextpdf.com/content/itext-7-converting-html-pdf-pdfhtml/chapter-7-frequently-asked-questions-about-pdfhtml/how-parse-multiple-html-files-one-pdf。由于某种原因,页面页脚存在格式问题。这jsFiddle链接 https://jsfiddle.net/Sparks245/uhxqdta6/3/到我的 PDF 渲染器正在使用的 HTML 代码。

下面是用于渲染 PDF 的 Java 代码(Test.html 与 fiddle 中的 HTML 代码相同):

package com.itextpdf.htmlsamples.chapter01;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.utils.PdfMerger;
import com.itextpdf.licensekey.LicenseKey;

/**
 * Can we parse different HTML files and combine them into one PDF?
 * Yes, this can be done in different ways. This example shows how
 * to create a PDF in memory for each HTML, then use PdfMerger to
 * merge the different PDFs into one, on a page per page basis.
 */
public class C07E01_CombineHtml {

    /** The Base URI of the HTML page. */
    public static final String BASEURI = "src/main/resources/html/";
    /** An array containing the paths to different HTML files. */
    public static final String[] SRC = {
            String.format("%sTest.html", BASEURI),
            String.format("%sTest.html", BASEURI),
            String.format("%sTest.html", BASEURI)
    };
    /** The target folder for the result. */
    public static final String TARGET = "target/results/ch07/";
    /** The path to the resulting PDF file. */
    public static final String DEST = String.format("%sbundle.pdf", TARGET);
    protected PageSize A4;

    /**
     * The main method of this example.
     *
     * @param args no arguments are needed to run this example.
     * @throws IOException Signals that an I/O exception has occurred.
     */
    public static void main(String[] args) throws IOException {
        LicenseKey.loadLicenseFile("C://Users//Sparks//Desktop//itextkey-0.xml");
        File file = new File(TARGET);
        file.mkdirs();
        new C07E01_CombineHtml().createPdf(BASEURI, SRC, DEST);
    }

    /**
     * Creates the PDF file.
     *
     * @param baseUri the base URI
     * @param src an array with the paths to different source HTML files
     * @param dest the path to the resulting PDF
     * @throws IOException Signals that an I/O exception has occurred.
     */
    public void createPdf(String baseUri, String[] src, String dest) throws IOException { 
        ConverterProperties properties = new ConverterProperties();
        properties.setBaseUri(baseUri);
        PdfWriter writer = new PdfWriter(dest);
        PdfDocument pdf = new PdfDocument(writer);
        PdfMerger merger = new PdfMerger(pdf);
        for (String html : src) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfDocument temp = new PdfDocument(new PdfWriter(baos));
            PageSize pageSize = PageSize.A4;
            temp.setDefaultPageSize(pageSize);
            HtmlConverter.convertToPdf(new FileInputStream(html), temp, properties);
            temp = new PdfDocument(new PdfReader(new ByteArrayInputStream(baos.toByteArray())));
            merger.merge(temp, 1, temp.getNumberOfPages());
            temp.close();
        }
        pdf.close();
    }
}

The 输出PDF文件 https://drive.google.com/file/d/1UskxGvc_IBV59PQLB5tvklvstDvtMnSL/view?usp=sharing有 6 页,无页脚。每页应有 3 页,尺寸为“A4”。

任何的意见都将会有帮助。


将 PageSize 更改为更大的值应该可以解决这一特定问题。 之后您可以缩小页面以获得 A4 页面的 PDF。 请查看下面的代码示例,了解如何执行此操作。

public static void main(String[] args) throws IOException {
    ByteArrayOutputStream pdf = createPdf("src/main/resources/SO47869248/html.html");
    // To get from A3 to A4 the size has to shrink 71%
    new SO47869248().scalePdf(DEST, new ByteArrayInputStream(pdf.toByteArray()), 0.7071f);
}

public static ByteArrayOutputStream createPdf(String htmlSrc) throws IOException {
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    ConverterProperties converterProperties = new ConverterProperties();
    converterProperties.setBaseUri(new File(htmlSrc).getParent());
    PdfWriter writer = new PdfWriter(output);
    PdfDocument pdfDocument = new PdfDocument(writer);
    PdfMerger merger = new PdfMerger(pdfDocument);
    for(int x=0; x < 3; x++){
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfDocument temp = new PdfDocument(new PdfWriter(baos));
        temp.setDefaultPageSize(PageSize.A3);
        HtmlConverter.convertToPdf(new FileInputStream(htmlSrc), temp, converterProperties);
        temp = new PdfDocument(new PdfReader(new ByteArrayInputStream(baos.toByteArray())));
        merger.merge(temp, 1, temp.getNumberOfPages());
        temp.close();
    }
    pdfDocument.close();

    return output;
}

public void scalePdf(String dest, ByteArrayInputStream input, float scale) throws IOException {
    // Create the source document
    PdfDocument srcDoc = new PdfDocument(new PdfReader(input));
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    ScaleDownEventHandler eventHandler = new ScaleDownEventHandler(scale);
    int n = srcDoc.getNumberOfPages();
    pdfDoc.addEventHandler(PdfDocumentEvent.START_PAGE, eventHandler);

    PdfCanvas canvas;
    PdfFormXObject page;
    for (int p = 1; p <= n; p++) {
        eventHandler.setPageDict(srcDoc.getPage(p).getPdfObject());
        canvas = new PdfCanvas(pdfDoc.addNewPage());
        page = srcDoc.getPage(p).copyAsFormXObject(pdfDoc);
        canvas.addXObject(page, scale, 0f, 0f, scale, 0f, 0f);
    }

    pdfDoc.close();
    srcDoc.close();
}

protected class ScaleDownEventHandler implements IEventHandler {
    protected float scale = 1;
    protected PdfDictionary pageDict;

    public ScaleDownEventHandler(float scale) {
        this.scale = scale;
    }

    public void setPageDict(PdfDictionary pageDict) {
        this.pageDict = pageDict;
    }

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
        PdfPage page = docEvent.getPage();
        page.put(PdfName.Rotate, pageDict.getAsNumber(PdfName.Rotate));

        scaleDown(page, pageDict, PdfName.MediaBox, scale);
        scaleDown(page, pageDict, PdfName.CropBox, scale);
    }

    protected void scaleDown(PdfPage destPage, PdfDictionary pageDictSrc, PdfName box, float scale) {
        PdfArray original = pageDictSrc.getAsArray(box);
        if (original != null) {
            float width = original.getAsNumber(2).floatValue() - original.getAsNumber(0).floatValue();
            float height = original.getAsNumber(3).floatValue() - original.getAsNumber(1).floatValue();
            PdfArray result = new PdfArray();
            result.add(new PdfNumber(0));
            result.add(new PdfNumber(0));
            result.add(new PdfNumber(width * scale));
            result.add(new PdfNumber(height * scale));
            destPage.put(box, result);
        }
    }
}

在本例中,我选择了 A3 页面大小常量。您还可以使用特定测量值创建 PageSize 对象。如下所示:

构造函数:

public PageSize(float width, float height)

Example:

PageSize pageSize = new PageSize(750, 1000);
PdfDocument temp = new PdfDocument(pageSize);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 iText pdfHTML 的 PDF 页面大小和格式 的相关文章

  • Java:无法从同一包中的不同类访问静态变量

    这很奇怪 因为我有一个可以访问 Frame dimension getWidth 的 Character 类 及其伙伴 getHeight 但是当我想在 Map 类中使用它时 Eclipse 强调了它并且无法给我反馈 运行该程序最终会出现
  • “java.net.MalformedURLException:未找到协议”读取到 html 文件

    我收到一个错误 java net MalformedURLException Protocol not found 我想读取网络上的 HTML 文件 mainfest uses permission android name android
  • 如何在 Antlr4 中为零参数函数编写语法

    我的函数具有参数语法 如下面的词法分析器和解析器 MyFunctionsLexer g4 lexer grammar MyFunctionsLexer FUNCTION FUNCTION NAME A Za z0 9 DOT COMMA L
  • GWT - 如何组织项目以拥有多个网页以及它们之间的导航

    我是 GET 的新手 顺便说一句 它给我留下了深刻的印象 并且发现它对于像我这样熟悉 C NET 桌面技术并愿意编写 Web 应用程序的人来说非常有吸引力 我根据 GWT Eclipse 向导生成的示例启动了自己的项目 该项目生成带有面板的
  • Spring RestTemplate 使用 cookie 遵循重定向

    最近我遇到了一个问题 我需要做一个GET请求远程服务 我假设使用一个简单的 servlet 并且 RestTemplate 返回Too many redirects 经过一番调查 似乎对指定远程服务发出的第一个请求实际上只是一个 302 重
  • 通往楼梯顶部的可能路径

    这是一个非常经典的问题 我听说谷歌在他们的面试中使用过这个问题 问题 制定一个递归方法 打印从楼梯底部到楼梯顶部的所有可能的独特路径 有 n 个楼梯 您一次只能走 1 步或 2 步 示例输出 如果它是一个有 3 级楼梯的楼梯 1 1 1 2
  • Integer.parseInt("0x1F60A") 以 NumberformatException 结束

    我尝试从数据库中获取长字符串内的表情符号代码 格式如下 0x1F60A 所以我可以访问代码 但它将是String 起初 我尝试通过执行以下操作来转换变量tv setText beforeEmo getEmijoByUnicode int e
  • 来自十六进制代码的 Apache POI XSSFColor

    我想将单元格的前景色设置为十六进制代码中的给定颜色 例如 当我尝试将其设置为红色时 style setFillForegroundColor new XSSFColor Color decode FF0000 getIndexed 无论我在
  • ConcurrentHashMap 内部是如何工作的?

    我正在阅读有关 Java 并发性的 Oracle 官方文档 我想知道Collection由返回 public static
  • 如何使用 Hibernate (EntityManager) 或 JPA 调用 Oracle 函数或过程

    我有一个返回 sys refcursor 的 Oracle 函数 当我使用 Hibernate 调用该函数时 出现以下异常 Hibernate call my function org hibernate exception Generic
  • 生成的序列以 1 开头,而不是注释中设置的 1000

    我想请求一些有关 Hibernate 创建的数据库序列的帮助 我有这个注释 下面的代码 在我的实体类中 以便为合作伙伴表提供单独的序列 我希望序列以 1000 开头 因为我在部署期间使用 import sql 将测试数据插入数据库 并且我希
  • Java:如何为山区时间创建 TimeZone 对象?

    必须不禁用夏令时 嗯 在这个清单 http en wikipedia org wiki List of tz database time zones在 zoneinfo 时区名称中 有很多声称是 山地时间 找到最适合您想要的那个 然后使用它
  • 如何在 Spring 属性中进行算术运算?

  • HashMap 值需要不可变吗?

    我知道 HashMap 中的键需要是不可变的 或者至少确保它们的哈希码 hashCode 不会改变或与另一个具有不同状态的对象发生冲突 但是 HashMap中存储的值是否需要与上面相同 为什么或者为什么不 这个想法是能够改变值 例如在其上调
  • JMenu 中的文本居中

    好吧 我一直在网上寻找有关此问题的帮助 但我尝试的任何方法似乎都不起作用 我想让所有菜单文本都集中在菜单按钮上 当我使用setHorizontalTextPosition JMenu CENTER 没有变化 事实上 无论我使用什么常量 菜单
  • 在 Google App-Engine JAVA 中将文本转换为字符串,反之亦然

    如何从字符串转换为文本 java lang String to com google appengine api datastore Text 反之亦然 Check Javadoc http code google com appengin
  • 使用按钮作为列表的渲染器

    我想使用一个更复杂的渲染器 其中包含列表的多个组件 更准确地说 类似于this https stackoverflow com questions 10840498 java swing 1 6 textinput like firefox
  • OpenCSV:将嵌套 Bean 映射到 CSV 文件

    我正在尝试将 bean 映射到 CSV 文件 但问题是我的 bean 具有其他嵌套 bean 作为属性 所发生的情况是 OpenCSV 遍历属性找到一个 bean 然后进入其中并映射该 bean 内的所有数据 如果找到另一个 bean 它就
  • Java中HashMap和ArrayList的区别?

    在爪哇 ArrayList and HashMap被用作集合 但我不明白我们应该在哪些情况下使用ArrayList以及使用时间HashMap 他们两者之间的主要区别是什么 您具体询问的是 ArrayList 和 HashMap 但我认为要完
  • 洪水填充优化:尝试使用队列

    我正在尝试创建一种填充方法 该方法采用用户指定的初始坐标 检查字符 然后根据需要更改它 这样做之后 它会检查相邻的方块并重复该过程 经过一番研究 我遇到了洪水填充算法并尝试了该算法 它可以工作 但无法满足我对 250 x 250 个字符的数

随机推荐