如何调整 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>
可能有几种方法可以解决您的问题:
- 尝试在 html 文件中设置指定的属性。
- 尝试使用下面建议的代码以适应 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()
)。
由于尺寸原因,将内容设置为 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>
可能有几种方法可以解决您的问题:
- 尝试在 html 文件中设置指定的属性。
- 尝试使用下面建议的代码以适应 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()
)。