itext5将HTML转成PDF问题中,如何在指定位置插入svg矢量图
- 生成pdf所需对象
Document document = new Document(PageSize.A4,50,50,50,50);
PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(dest));
- 将html转Element
利用xml worker将html转成itext中的ElementList对象
ElementList list = MyXMLWorkerHelper.parseToElementList(htmlfile);
[itext官方示例](https://itextpdf.com/en/resources/examples/itext-5-legacy/xml-worker-examples)
- 解析出ElementList中自己定义的占位符去找出应该在那个地方插入图片
在这里我因为在html中用的是div标签去标识的图片
这段代码主要是可以解决itext5只能识别html4的标签而不识别svg标签引发的
这段代码最大的意义在于可以准确的将svg或者其他的图片能准确的放在你html定位的位置
其中用到了XML Worker(html2pdf的一个工具包),PdfGraphics2D (将svg化成pdf),
PDFReader读取pdf(可以将一个pdf读取出来,进行一系列的操作,我这里只是为了取图片)
在这里把这个小demo的难点列出来:
1.将svg放到pdf中(有两种方法,一会引发难定位,二会引发图都一样)
2.代码走的是第二个方法,解决图都一样是用的pdfreader再解析一遍
//遍历集合
for (Element topElem : list) {
//这里因为我用的是body标签中套入div进行编写的html(这一步可以省略判断)
if (topElem instanceof PdfDiv) {
PdfDiv topPdfDiv = (PdfDiv)topElem;
for (Element element : topPdfDiv.getContent()) {
//判断是否是自定义的图片(div标签)
if (element instanceof PdfDiv) {
PdfDiv imgPdfDiv = (PdfDiv) element;
try {
//这个是项目中的一个生成svg图片字符串的方法(和本次问题无关,返回的是svg的字符串)
String img = getImg(imageStyle.id, query, imageStyle.width, imageStyle.height, imageStyle.title);
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024 ); //这个就是svg画出来的pdf输出流
//下面的一段代码是将svg化成pdf(官方也有示例代码:https://itextpdf.com/en/resources/examples/itext-5-legacy/graphics2d-examples)
Document dt = new Document(new Rectangle(width, height));
PdfWriter writer = PdfWriter.getInstance(dt, baos);
dt.open();
PdfContentByte cb = writer.getDirectContent();
PdfTemplate svgTemplate = cb.createTemplate(width, height);
PdfGraphics2D g2d = new PdfGraphics2D(svgTemplate, width, height);
SVGDocument city = factory.createSVGDocument(imageStyle.query, new StringReader(img));
//SVGDocument city = factory.createSVGDocument("results/img.svg");
GraphicsNode mapGraphics = builder.build(ctx, city);
mapGraphics.paint(g2d);
g2d.dispose();
cb.addTemplate(svgTemplate, 0, 0);
dt.close();
//下面的代码是问题的关键,原因是在上面生成的svgTemplate如果直接放入下面的list会导致pdf中的所有图片都是一样的
//这段代码其实就是pdfReading的应用
PdfReader svgReader = new PdfReader(baos.toByteArray());
PdfImportedPage svgPage = pdfWriter.getImportedPage(svgReader, 1);
Image instance = Image.getInstance(svgPage);
instance.setWidthPercentage(80); //将图片缩放的80%
instance.setAlignment(Element.ALIGN_CENTER); //图片居中
//这样放的好处就是会按照你之前的定位放进去,而不用去操心图片定位问题
ArrayList<Element> textContent = new ArrayList<>();
textContent.add(instance);
imgPdfDiv.setContent(textContent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
document.add(topElem);
document.close();
}
这个代码就已经解决了svg插入到pdf中的问题了。代码的来源主要是项目经理帮忙攻克的,其中在解决图片重复的问题上花了两天时间,原因是不熟悉itext,不知道svg还可以转成什么Element的子类添加到pdf中。
希望看到这段代码可以解决你们想要解决的问题。