我使用iText(版本7.1.1)使用HtmlConverter(html2pdf版本2.0.1)将html转换为pdf:
public static ByteArrayOutputStream htmlToPDFStream(String htmlBody)
throws DocumentException, IOException {
ConverterProperties props = new ConverterProperties();
FontProvider fp = new DefaultFontProvider(true, false, false);
for (String font : FONTS) {
FontProgram fontProgram = FontProgramFactory.createFont(font);
fp.addFont(fontProgram);
}
props.setFontProvider(fp);
com.itextpdf.kernel.pdf.PdfWriter writer = new com.itextpdf.kernel.pdf.PdfWriter(outputStream);
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf);
List<IElement> elements = HtmlConverter.convertToElements(new ByteArrayInputStream(htmlBody.getBytes(StandardCharsets.UTF_8)), props);
for (IElement element : elements) {
document.add((IBlockElement)element);
}
document.close();
return outputStream;
}
如果HTML字符串包含小图像(小于默认页面尺寸A4),则效果很好。 但是,如果我的图像大于默认页面宽度,则结果将以pdf格式裁剪图像。
如果图片大于默认的pdf页面大小,有没有办法让iText自动调整大小?
答案 0 :(得分:1)
布局中的图像具有自动缩放属性,这会导致所需的行为。您需要定义自定义ITagWorker
才能将此属性实际添加到生成的图像元素中。
您还必须定义自定义ITagWorkerFactory
,以便为图片使用新的ITagWorker
。
代码非常简单,你只需要仔细地将所有内容绑在一起:
class CustomImageWorker extends ImgTagWorker {
public CustomImageWorker(IElementNode element, ProcessorContext context) {
super(element, context);
}
@Override
public IPropertyContainer getElementResult() {
return ((Image)super.getElementResult()).setAutoScale(true);
}
}
ITagWorkerFactory customFactory = new DefaultTagWorkerFactory() {
@Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if (TagConstants.IMG.equals(tag.name())) {
return new CustomImageWorker(tag, context);
} else {
return null;
}
}
};
之后,只需将标签工厂设置为道具:props.setTagWorkerFactory(customFactory);
CSS级别的另一个解决方案是根据媒体设备设置指定不同的图像宽度和高度,例如设备宽度和高度。请参阅@media
CSS规则文档。
UPD 如果您没有为图片定义任何width
或height
CSS属性,则可以直接将其大小与页面大小进行比较,但请保留介意px转换率。例如:
@Override
public IPropertyContainer getElementResult() {
Image result = ((Image)super.getElementResult());
if (!processed) {
float imageWidth = result.getImageScaledWidth();
float pageMargin = 36 * 2;
float maxWidth = PageSize.A4.getWidth() - pageMargin;
float maxHeight = PageSize.A4.getHeight() - pageMargin;
if (imageWidth * 0.75 > maxWidth) {
result.scaleToFit(maxWidth / 0.75f, maxHeight / 0.75f);
}
processed = true;
}
return result;
}