gpt4 book ai didi

java - 在itext 7中将html转换为pdf时如何仅获得某些页面的横向方向?

转载 作者:行者123 更新时间:2023-12-04 09:32:23 31 4
gpt4 key购买 nike

我使用 将 HTML 转换为 PDF iText7 convertToPDF() pdfHTML 的方法。我想更改 PDF 文档中几个特定页面的页面方向。这些页面的内容是动态的,我们无法猜测横向应该有多少页(即动态表的内容可能会超过一页)
当前情况:我创建了一个自定义工作器(实现 ITagWorker ),它可以浏览标签 <landscape/> 之后的页面。

public byte[] generatePDF(String html) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PdfWriter pdfWriter = new PdfWriter(byteArrayOutputStream);
PdfDocument pdfDocument = new PdfDocument(pdfWriter);
try {

ConverterProperties properties = new ConverterProperties();

properties.setTagWorkerFactory(
new DefaultTagWorkerFactory() {
@Override
public ITagWorker getCustomTagWorker(
IElementNode tag, ProcessorContext context) {
if ("landscape".equalsIgnoreCase(tag.name())) {
return new LandscapeDivTagWorker();
}
return null;
}
} );

MediaDeviceDescription mediaDeviceDescription = new MediaDeviceDescription(MediaType.PRINT);
properties.setMediaDeviceDescription(mediaDeviceDescription);

HtmlConverter.convertToPdf(html, pdfDocument, properties);
} catch (IOException e) {
e.printStackTrace();
}
pdfDocument.close();
return byteArrayOutputStream.toByteArray();
}
自定义 worker :
public class LandscapeDivTagWorker implements ITagWorker {

@Override
public void processEnd(IElementNode element, ProcessorContext context) {
}

@Override
public boolean processContent(String content, ProcessorContext context) {
return false;
}

@Override
public boolean processTagChild(ITagWorker childTagWorker, ProcessorContext context) {
return false;
}

@Override
public IPropertyContainer getElementResult() {
return new AreaBreak(new PageSize(PageSize.A4).rotate());
}
}
有没有办法定义应该横向显示的所有内容?
就像是:
<p>Display in portrait</p>
<landscape>
<div>
<p>display in landscape</p>

<table>
..
</table>
</div>
</landscape>
或使用 CSS 类:
<p>Display in portrait</p>
<div class="landscape">
<p>display in landscape</p>

<table>
..
</table>
</div>
结果 => 1 页纵向和其他页面 s 风景 (所有的 div 内容都应该是横向的)
PS:我按照这个提示 Change page orientation for only some pages in the resulting PDF (created out of html)通过使用自定义 CssApplierFactory 但结果是一样的 => 只是使用横向类的第一页是横向的,而表格的其他内容是纵向的

最佳答案

这样做实际上相当棘手,但整个机制仍然足够灵活以适应这种需求。
我们将致力于支持以下语法:

<p>Display in portrait</p>
<landscape>
<div>
<p>display in landscape</p>
<p>content</p>
.....
<p>content</p>
</div>
</landscape>
<p> After portrait </p>
首先,我们需要先将 HTML 内容转换为元素,然后将这些元素添加到文档中,而不是直接将 HTML -> PDF 转换。这是必需的,因为在 HTML 的情况下,根据 CSS 规范有一个单独的页面大小处理机制,它不够灵活,无法满足您的要求,因此我们将为此使用 native iText 布局机制。
这个想法是,除了通过将参数传递给 AreaBreak 来自定义新页面大小之外我们还将更改 PdfDocument 的默认页面大小以便所有后续页面都使用该自定义新页面大小创建。为此,我们需要通过 PdfDocument一直。高级代码如下所示:
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFilePath));
ConverterProperties properties = new ConverterProperties();
properties.setTagWorkerFactory(new CustomTagWorkerFactory(pdfDocument));

Document document = new Document(pdfDocument);
List<IElement> elements = HtmlConverter.convertToElements(new FileInputStream(inputHtmlPath), properties);
for (IElement element : elements) {
if (element instanceof IBlockElement) {
document.add((IBlockElement) element);
}
}

pdfDocument.close();
自定义标签 worker 工厂也几乎没有变化——它只是通过 PdfDocument与标签 worker 一起:
private static class CustomTagWorkerFactory extends DefaultTagWorkerFactory {
PdfDocument pdfDocument;

public CustomTagWorkerFactory(PdfDocument pdfDocument) {
this.pdfDocument = pdfDocument;
}

@Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if ("landscape".equalsIgnoreCase(tag.name())) {
return new LandscapeDivTagWorker(tag, context, pdfDocument);
}
return null;
}
}
LandscapeDivTagWorker的想法是创建一个 Div包装并将 <landscape> 的内部内容放在那里标签,但也用 AreaBreak 包围它元素 - 前一个将强制横向分页并更改整个文档的默认页面大小,而后一个将恢复所有内容 - 强制拆分为纵向页面大小并将默认页面大小设置为纵向。请注意,我们还为 AreaBreak 设置了自定义渲染器与 setNextRenderer在中断时实际设置默认页面大小:
private static class LandscapeDivTagWorker extends DivTagWorker {
private PdfDocument pdfDocument;

public LandscapeDivTagWorker(IElementNode element, ProcessorContext context, PdfDocument pdfDocument) {
super(element, context);
this.pdfDocument = pdfDocument;
}

@Override
public IPropertyContainer getElementResult() {
IPropertyContainer baseElementResult = super.getElementResult();
if (baseElementResult instanceof Div) {
Div div = new Div();
AreaBreak landscapeAreaBreak = new AreaBreak(new PageSize(PageSize.A4).rotate());
landscapeAreaBreak.setNextRenderer(new DefaultPageSizeChangingAreaBreakRenderer(landscapeAreaBreak, pdfDocument));
div.add(landscapeAreaBreak);
div.add((IBlockElement) baseElementResult);
AreaBreak portraitAreaBreak = new AreaBreak(new PageSize(PageSize.A4));
portraitAreaBreak.setNextRenderer(new DefaultPageSizeChangingAreaBreakRenderer(portraitAreaBreak, pdfDocument));
div.add(portraitAreaBreak);
baseElementResult = div;
}
return baseElementResult;
}
}
自定义区域中断渲染器的实现非常简单——我们只将默认页面大小设置为 PdfDocument - 其余的都是在我们扩展的默认实现下完成的:
private static class DefaultPageSizeChangingAreaBreakRenderer extends AreaBreakRenderer {
private PdfDocument pdfDocument;
private AreaBreak areaBreak;

public DefaultPageSizeChangingAreaBreakRenderer(AreaBreak areaBreak, PdfDocument pdfDocument) {
super(areaBreak);
this.pdfDocument = pdfDocument;
this.areaBreak = areaBreak;
}

@Override
public LayoutResult layout(LayoutContext layoutContext) {
pdfDocument.setDefaultPageSize(areaBreak.getPageSize());
return super.layout(layoutContext);
}
}
因此,您将获得类似于屏幕截图中的页面设置:
result

关于java - 在itext 7中将html转换为pdf时如何仅获得某些页面的横向方向?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62778803/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com