如何调整 html 内容的大小使其适合 A4 pdf?

How to resize html content so it will fit in A4 pdf?

由于尺寸原因,将内容设置为 A4 pdf 时出现问题。我尝试过的事情:溢出换行、自动换行、自定义 customSplitCharacter class、设置最大宽度 html、table、正文。是否有任何想法如何设置 pdf 大小以便 table 自动适合它(无需滚动)?我的 itext 依赖项:itext7-core(7.1.13), html2pdf (3.0.2),itextpdf(5.5.13.2)

PDF浏览器: 网页浏览:

  public byte[] testingGetPDFInByte() {
    String html = new String(testing('', 1, 1,
        Collections.emptyList()).toByteArray());

    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    WriterProperties writerProperties = new WriterProperties();
    writerProperties.addXmpMetadata();

    PdfWriter pdfWriter = new PdfWriter(baos, writerProperties);
    PdfDocument pdfDoc = new PdfDocument(pdfWriter);
    pdfDoc.setDefaultPageSize(PageSize.A4);
    FontProvider fontProvider = new DefaultFontProvider(true, true, false);
    genDocConfigProperties.getFontPaths().forEach(fontProvider::addFont);

    ConverterProperties props = new ConverterProperties();
    props.setFontProvider(fontProvider);
    props.setImmediateFlush(false);

    final com.itextpdf.layout.Document document = HtmlConverter.convertToDocument(html, pdfDoc, props);
    document.flush();
    document.close();
    return baos.toByteArray();  
}

Table 部分 html:

        <xsl:variable name="stl" select="'border:1px solid black;padding:5px;page-break-inside:avoid;max-width:30px;word-wrap: break-word;vertical-align:top;'" />
<table style="border-collapse: collapse;margin:5px;table-layout: fixed;">
  <tr style="{$stl}">
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">№</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">Дата прибытия</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">Станция отправления</span>
    </td>
    <td style="{$stl}" colspan="3">
      <span style="font-weight: bold;">СС</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">Дата отправления</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">Станция отправления</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">Код операции</span>
    </td>
    <td style="{$stl}" colspan="3">
      <span style="font-weight: bold;">Пассажир</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">Стоимость места</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">Номер места</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">Номер и тип привилегии</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">Дата продажи</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">Терминал</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">Билет</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">№ поезда</span>
    </td>
    <td style="{$stl}" rowspan="2">
      <span style="font-weight: bold;">№ вагона</span>
    </td>
  </tr>
  <tr style="{$stl}">
    <td style="{$stl}">
      <span style="font-weight: bold;">Код</span>
    </td>
    <td style="{$stl}">
      <span style="font-weight: bold;">Описание</span>
    </td>
    <td style="{$stl}">
      <span style="font-weight: bold;">Продажа</span>
    </td>
    <td style="{$stl}">
      <span style="font-weight: bold;">ФИО</span>
    </td>
    <td style="{$stl}">
      <span style="font-weight: bold;">Тип документа</span>
    </td>
    <td style="{$stl}">
      <span style="font-weight: bold;">№ документа</span>
    </td>
  </tr>
  <xsl:for-each select="responseTikets">
    <tr style="{$stl}">
      <td style="{$stl}">
        <xsl:value-of select="position()" />
      </td>

可能有几种方法可以解决您的问题:

  1. 尝试在 html 文件中设置指定的属性。
  2. 尝试使用下面建议的代码以适应 A4 页面大小的 pdf html table。这里 table 被缩放并作为 formXObject 放在 Canvas 中,并以设置的大小装入矩形。所以如果 table 宽度增加,它应该被缩放以适合 pdf 页面大小。
try (InputStream is = FileUtil.getInputStreamForFile(path to html file)) {
    List<IElement> iElements = HtmlConverter.convertToElements(is);
    Div div = new Div();
    
    for (IElement elem : iElements) {
        if (elem instanceof IBlockElement) {
            div.add((IBlockElement) elem);
        } else if (elem instanceof Image) {
            div.add((Image) elem);
        } else if (elem instanceof AreaBreak) {
            div.add((AreaBreak) elem);
        } else {
            Assert.fail("The #convertToElements method gave element which is unsupported as root element, it's unexpected.");
        }
    }
    PageSize pageSize = PageSize.A4;
    
    try (PdfDocument pdfDocument = new PdfDocument(new PdfWriter(output pdf path))) {
        pdfDocument.setDefaultPageSize(pageSize);
        PdfCanvas pdfCanvas = new PdfCanvas(new PdfStream(), new PdfResources(), pdfDocument);
        try (Canvas canvas = new Canvas(pdfCanvas, new Rectangle(Float.MAX_VALUE, Float.MAX_VALUE))) {
            Rectangle htmlSize = div.createRendererSubTree().setParent(canvas.getRenderer())
                .layout(new LayoutContext(new LayoutArea(1, new Rectangle(
                    pageSize.getWidth(),
                    pageSize.getHeight()
                ))))
                    .getOccupiedArea()
                    .getBBox();
    
            PdfFormXObject formXObject = new PdfFormXObject(htmlSize);
            try (Canvas canvasForDiv = new Canvas(formXObject, pdfDocument)) {
                canvasForDiv.add(div);
            }

            PdfPage pageNewDoc = pdfDocument.addNewPage();
            PdfCanvas canvasToAddXObject = new PdfCanvas(pageNewDoc);
           canvasToAddXObject.addXObjectFittedIntoRectangle(formXObject, fit(new Rectangle(0, 0, formXObject.getWidth(), formXObject.getHeight()), pageNewDoc.getPageSize()));
        }
    }
}

private static Rectangle fit(Rectangle img, Rectangle page) {
    float ws = page.getWidth()/img.getWidth();
    float hs =  page.getHeight()/img.getHeight();
    float scale = Math.min(ws, hs);
        
    return new Rectangle(0,page.getHeight()-img.getHeight()*scale, img.getWidth()*scale, img.getHeight()*scale);
}

您也可以使用旋转后的页面大小(例如 PageSize.A4.rotate())。