itext7 只为 pdfa 在标题中嵌入字体 1 次

问题描述

我正在 pdf/a 文档上应用标题

我将字体嵌入到文档中,如果我有数百页也没有问题,在创建的 pdf 中,我只看到一种字体嵌入到文档属性中。

现在我使用画布添加标题,如许多示例所示。

起初它抛出错误,因为它说必须嵌入字体。

当我嵌入字体时,它可以工作,但在文档属性中,我看到每个页面都重复使用该字体。

因此文档 kb 大小增长了很多。

我只想嵌入一次字体。

Spring Boot,但我认为这无关紧要。

header 代码

@Slf4j
public class Header implements IEventHandler {
    
    private IFontProviderService fontProviderService;
    private String logoPath;

    private String header;
    private List<String> subHeaders;
    
    public Header(IFontProviderService fontProviderService,String logoPath,String header,List<String> subHeaders) {
        this.fontProviderService = fontProviderService;
        this.header = header;
        this.subHeaders = subHeaders;
        this.logoPath = logoPath;
    }

    @Override
    public void handleEvent(Event event) {

        try {
            PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
            PdfDocument pdf = docEvent.getDocument();
            pdfpage page = docEvent.getPage();
            PdfDictionary pdfObject = page.getPdfObject();

            PdfCanvas headerPdfCanvas = new PdfCanvas(page.newContentStreamBefore(),page.getResources(),pdf);
            Rectangle headerRect = new Rectangle(35,740,495,96);
            Canvas headerCanvas = new Canvas(headerPdfCanvas,headerRect);

            headerCanvas.setFont(fontProviderService.getDefaultPdfFont());

            headerCanvas.enableAutoTagging(page);
            CreateHeaderContent(headerCanvas);
            headerCanvas.close();

        } catch (Exception e) {
            log.error("Error in header settings.",e);
        }

    }

    private void CreateHeaderContent(Canvas canvas) throws MalformedURLException {
        Table table = new Table(UnitValue.createPercentArray(new float[] { 80,20 }));
        table.setWidth(UnitValue.createPercentValue(100));

        Cell cell1 = new Cell().add(new Paragraph(header).setBold().setFontSize(11).setTextAlignment(TextAlignment.LEFT));
        for (int i = 0; i < subHeaders.size(); i++) {
            cell1.add(new Paragraph(subHeaders.get(i)).setFontSize(8).setTextAlignment(TextAlignment.LEFT));
        }
        cell1.setBorder(Border.NO_BORDER);
        table.addCell(cell1);

        ImageData imageData = ImageDataFactory.create(logoPath);
        Image image = new Image(imageData);
        image.getAccessibilityProperties().setAlternateDescription("...");
        Cell cell2 = new Cell().add(image.setTextAlignment(TextAlignment.RIGHT));
        cell2.setBorder(Border.NO_BORDER);
        cell2.setVerticalAlignment(VerticalAlignment.MIDDLE);
        table.addCell(cell2);

        canvas.add(table);
    }
}




@Slf4j
@Service
public class FontProviderService implements IFontProviderService {

    @Value("${pdf.resources.external.path}")
    private String staticResourcesPath;
    
    @Override
    public FontProvider getFontProvider() throws IOException {
        FontProvider fontProvider = new FontProvider("DMSans-Regular");
        fontProvider.addFont(FontProgramFactory.createFont(staticResourcesPath + "pdf/fonts/DMSans-Regular.ttf"));
        fontProvider.addFont(FontProgramFactory.createFont(staticResourcesPath + "pdf/fonts/DMSans-Bold.ttf"));
        fontProvider.addFont(FontProgramFactory.createFont(staticResourcesPath + "pdf/fonts/DMSans-Italic.ttf"));
        fontProvider.addFont(FontProgramFactory.createFont(staticResourcesPath + "pdf/fonts/DMSans-BoldItalic.ttf"));
        fontProvider.addFont(FontProgramFactory.createFont(staticResourcesPath + "pdf/fonts/DMSans-Medium.ttf"));
        fontProvider.addFont(FontProgramFactory.createFont(staticResourcesPath + "pdf/fonts/DMSans-MediumItalic.ttf"));
        return fontProvider;
    }

    @Override
    public PdfFont getDefaultPdfFont() throws IOException {
        String defaultFontFamily = this.getFontProvider().getDefaultFontFamily();
        Collection<FontInfo> fonts = this.getFontProvider().getFontSet().getFonts();
        FontInfo fontInfo = fonts.stream().filter(f -> f.getFontName().equals(defaultFontFamily)).findFirst().get();
        PdfFont pdfFont = this.getFontProvider().getPdfFont(fontInfo);
        return pdfFont;
    }

}

解决方法

...Spring 以某种方式与它有关...至少在我编写服务的方式...

嗯...实际上在我的情况下,问题只是我如何使用服务冲刺来检索 fontProvider 和字体。

我将整个 fontProviderService 传递给我的处理程序:

public Header(IFontProviderService fontProviderService,String logoPath,String header,List<String> subHeaders)

并且每次都打电话:

headerCanvas.setFont(fontProviderService.getDefaultPdfFont());

这相当于每次创建一个新的提供者:

FontProvider fontProvider = new FontProvider("DMSans-Regular");

重点是 FontProvider 对象和 PdfFont 对象必须始终相同

这样修改我的处理程序:

@Slf4j
public class Header implements IEventHandler {
    
    private FontProvider fontProvider;
    private PdfFont pdfFont;

    private String logoPath;
    
    private String header;
    private List<String> subHeaders;
    
    public Header(FontProvider fontProvider,PdfFont pdfFont,List<String> subHeaders) {
        this.fontProvider = fontProvider;
        this.pdfFont = pdfFont;
        this.header = header;
        this.subHeaders = subHeaders;
        this.logoPath = logoPath;
    }

    @Override
    public void handleEvent(Event event) {

        try {
            PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
            PdfDocument pdf = docEvent.getDocument();
            PdfPage page = docEvent.getPage();
            PdfDictionary pdfObject = page.getPdfObject();

            PdfCanvas headerPdfCanvas = new PdfCanvas(page.newContentStreamBefore(),page.getResources(),pdf);
            Rectangle headerRect = new Rectangle(35,740,495,96);
            Canvas headerCanvas = new Canvas(headerPdfCanvas,headerRect);

            headerCanvas.setFontProvider(fontProvider);
            headerCanvas.setFont(pdfFont);

            headerCanvas.enableAutoTagging(page);
            CreateHeaderContent(headerCanvas);
            headerCanvas.close();

        } catch (Exception e) {
            log.error("Error in header settings.",e);
        }

    }

    private void CreateHeaderContent(Canvas canvas) throws MalformedURLException {
        Table table = new Table(UnitValue.createPercentArray(new float[] { 80,20 }));
        table.setWidth(UnitValue.createPercentValue(100));

        Cell cell1 = new Cell().add(new Paragraph(header).setBold().setFontSize(11).setTextAlignment(TextAlignment.LEFT));
        for (int i = 0; i < subHeaders.size(); i++) {
            cell1.add(new Paragraph(subHeaders.get(i)).setFontSize(8).setTextAlignment(TextAlignment.LEFT));
        }
        cell1.setBorder(Border.NO_BORDER);
        table.addCell(cell1);

        ImageData imageData = ImageDataFactory.create(logoPath);
        Image image = new Image(imageData);
        image.getAccessibilityProperties().setAlternateDescription("...");
        Cell cell2 = new Cell().add(image.setTextAlignment(TextAlignment.RIGHT));
        cell2.setBorder(Border.NO_BORDER);
        cell2.setVerticalAlignment(VerticalAlignment.MIDDLE);
        table.addCell(cell2);

        canvas.add(table);
    }
}

为了完整起见,我从 Service 中删除了 getDefaultFont,这是调用 Handler 的 pdf 创建者的摘录:

    FontProvider fontProvider = fontProviderService.getFontProvider();
    String defaultFontFamily = fontProvider.getDefaultFontFamily();
    Collection<FontInfo> fonts = fontProvider.getFontSet().getFonts();
    FontInfo fontInfo = fonts.stream().filter(f -> f.getFontName().equals(defaultFontFamily)).findFirst().get();
    PdfFont defaultPdfFont = fontProvider.getPdfFont(fontInfo);

...

        converterProperties.setFontProvider(fontProvider);
        
        Header headerHandler = new Header(fontProvider,defaultPdfFont,staticResourcesPath + "....png","...","...");
        pdf.addEventHandler(PdfDocumentEvent.START_PAGE,headerHandler);