当前位置: 首页 > 知识库问答 >
问题:

使用iText生成PDF时,如果需要多次切换字体,则文件大小会变得太大

淳于乐池
2023-03-14

我有我的PDF的一部分,我需要使用一种字体作为其Unicode符号,其余的段落应该是不同的字体。(它类似于“1. a2. b3. c”,其中“1.”是Unicode符号/字体,“a”是另一种字体)我遵循了布鲁诺在这里描述的方法: iText 7:如何构建一个混合不同字体的段落?它可以很好地生成PDF。问题是PDF的文件大小从大约20MB到大约100MB,相比之下,只使用一种字体和一个文本元素。本节在文档中重复使用了数千次。我想知道是否有一种方法可以减少切换字体的影响,或者以某种方式减少整个文档的文件大小。

样式创建伪代码:

Style style1 = new Style();
Style style2 = new Style();
PdfFont font1 = PdfFontFactory.createFont(FontProgramFactory.createFont(fontFile1), PdfEncodings.IDENTITY_H, true);
style1.setFont(font1).setFontSize(8f).setFontColor(Color.DARK_GRAY);
PdfFont font2 = PdfFontFactory.createFont(FontProgramFactory.createFont(fontFile2), "", false);
style2.setFont(font2).setFontSize(8f).setFontColor(Color.DARK_GRAY);

编写文本/段落伪代码:

Div div = new Div().setPaddingLeft(3).setMarginBottom(0).setKeepTogether(true);
Paragraph paragraph = new Paragraph();
loop up to 25 times: {
    Text unicodeText = new Text(unicodeSymbol + " ").addStyle(style1);
    paragraph.add(unicodeText);
    Text plainText = new Text(plainText + " ").addStyle(style2);
    paragraph.add(plainText);
}
div.add(paragraph);

这种文字/段落的书写已经进行了数千次,构成了文档的大部分。基本上,文档由数千个具有相应代码的“建筑”组成,这些代码具有类别。我需要将该类别的索引作为unicode符号,然后在该建筑的段落中使用所有相应的代码。

以下是可复制代码:

    float offSet = 50;
    Integer leading = 10;
    DateFormat format = new SimpleDateFormat("yyyy_MM_dd_kkmmss");
    String formattedDate = format.format(new Date());
    String path = "/tmp/testing_pdf_"+formattedDate + ".pdf";
    File targetPdfFile = new File(path);
    PdfWriter writer = new PdfWriter(path, new WriterProperties().addXmpMetadata());
    PdfDocument pdf = new PdfDocument(writer);
    pdf.setTagged();
    PageSize pageSize = PageSize.LETTER;
    Document document = new Document(pdf, pageSize);
    document.setMargins(offSet, offSet, offSet, offSet);
    byte[] font1file = IOUtils.toByteArray(FileUtility.getInputStreamFromClassPath("fonts/Garamond-Premier-Pro-Regular.ttf"));
    byte[] font2file = IOUtils.toByteArray(FileUtility.getInputStreamFromClassPath("fonts/Quivira.otf"));
    PdfFont font1 = PdfFontFactory.createFont(FontProgramFactory.createFont(font1file), "", true);
    PdfFont font2 = PdfFontFactory.createFont(FontProgramFactory.createFont(font2file), PdfEncodings.IDENTITY_H, true);
    Style style1 = new Style().setFont(font1).setFontSize(8f).setFontColor(Color.DARK_GRAY);
    Style style2 = new Style().setFont(font2).setFontSize(8f).setFontColor(Color.DARK_GRAY);
    float columnGap = 5;
    float columnWidth = (pageSize.getWidth() - offSet * 2 - columnGap * 2) / 3;
    float columnHeight = pageSize.getHeight() - offSet * 2;
    Rectangle[] columns = {
            new Rectangle(offSet, offSet, columnWidth, columnHeight),
            new Rectangle(offSet + columnWidth + columnGap, offSet, columnWidth, columnHeight),
            new Rectangle(offSet + columnWidth * 2 + columnGap * 2, offSet, columnWidth, columnHeight)};
    document.setRenderer(new ColumnDocumentRenderer(document, columns));
    for (int j = 0; j < 5000; j++) {
        Div div = new Div().setPaddingLeft(3).setMarginBottom(0).setKeepTogether(true);
        Paragraph paragraph = new Paragraph().setFixedLeading(leading);
//            StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < 26; i++) {
            paragraph.add(new Text("\u3255 ").addStyle(style2));
            paragraph.add(new Text("test ").addStyle(style1));
//                stringBuilder.append("\u3255 ").append(" test ");
        }
//            paragraph.add(stringBuilder.toString()).addStyle(style2);

        div.add(paragraph);
        document.add(div);
    }
    document.close();

在创建可复制代码时,我发现这与被标记的文档有关。如果删除将其标记为已标记的行,则会大大减小文件大小。

您还可以通过使用注释掉的字符串生成器(使用一种字体而不是两种字体)来减小文件大小。(注释掉for循环中的两个“段落.添加”)这反映了我代码中的问题。

共有1个答案

龙俊德
2023-03-14

问题不在于字体本身。问题源于您正在创建带标签的PDF。带标签的文档中有很多PDF对象,需要在文件中留出大量空间。

我无法再现您的20MB vs 100MB结果。在我的机器上,无论是一种字体还是两种字体,但是有两个Text元素,结果文件大小是~44MB。

要在创建大型标记文档时压缩文件,应使用完全压缩模式,该模式压缩所有PDF对象,而不仅仅是流。

要激活完全压缩模式,请使用WriterProperties创建一个PdfWriter实例:

PdfWriter writer = new PdfWriter(outFileName, 
                  new WriterProperties().setFullCompressionMode(true));

此设置将我的文件大小从

请注意,您使用的是iText7.0. x,而7.1. x行已经发布,现在是iText的主线,所以我建议您更新到最新版本。

 类似资料:
  • 我希望在复制现有的pdf文件时,文件大小大致相同。我不明白为什么尺寸会增加这么多。 我也试过PdfCopy类。我使用PDFcopy遵循了2种方法: 逐页复制。 对pdfcopy对象调用setMergeFields(),然后调用pdfcopy.AddDocument(reader); 但这两种方法的问题都是,它会从pdf文件中丢弃一些非内容的元数据,因此当Adobe Reader打开新的pdf时会损

  • 我正在使用SVG将一些lat-lons映射为折线。这管用。我现在要添加一些适当的可缩放大小的文本。 这个简化的示例应该显示三个不同大小的字母。Firefox只显示2个,每个大小相同。Chrome、Opera和Edge都不显示字母。有一些行显示字母应该在哪里,所以我知道它在视区内。

  • 我正在使用iText生成一些PDF,这些PDF有一些中文字符(简体中文-GB2312),但是我无法用这些字符生成PDF。 谁能告诉我哪里错了? 我尝试使用各种创作形式,但没有成功: 有人能帮我吗? 添加问题,这是我当前的测试代码:

  • 这段代码第一次可以运行得很好,但是当我第二次运行app时,它不会立即生成PDF文件。

  • 问题内容: 我正在使用iText生成一些PDF,这些pdf具有一些汉字(简体中文-GB2312),但是我无法使用这些字符生成pdf。 谁能告诉我我哪里错了? 我尝试使用各种形式的创作,但没有成功: 有人可以帮我吗? 添加问题,这是我当前的测试代码: 问题答案: 您的CLASSPATH中有iText jar,但是您忘记添加(正确的)itext-asian.jar。 请从此处下载额外的jar ZIP文

  • 模仿网易新闻客户端以及新浪微博,左右滑动可以加载新视图,推出当前视图,返回上一级视图时,上一级视图有渐隐渐显和大小渐变的效果。 [Code4App.com]