```
4. 将html中的布局格式转化到pdf
4.1 示例: 后台这边基本不改,主要是前端的css的修改。根据设备的类型调整pdf页面的大小,渲染符合条件的文档。核心是@media only screen
```
//这是css布局,不同的页面设置不同的布局方式
/*Desktop*/
@media only screen and (min-width: 768px ) {
.col-1 {width:24.9%;}
.col-2 {width: 33.32%;}
.col-3 {width: 49%;}
.col-4 {width: 99%;}
p{
font-size: 12pt;
}
h1{
font-size: 20pt;
}
h2{
font-size:16pt
}
}
......
```
```
//后台代码
String html = "layout.html";
String htmlLoc = BASEURI + html;
PdfWriter writer = new PdfWriter("deskLayoutToPdf.pdf");
PdfDocument pdf = new PdfDocument(writer);
pdf.setTagged();
PageSize pageSize = PageSize.A4.rotate();
pdf.setDefaultPageSize(pageSize);
ConverterProperties properties = new ConverterProperties();
properties.setBaseUri(BASEURI);
//核心,对应css样式中的 @media only screen
MediaDeviceDescription mediaDeviceDescription = new MediaDeviceDescription(MediaType.SCREEN);
mediaDeviceDescription.setWidth(pageSize.getWidth());
properties.setMediaDeviceDescription(mediaDeviceDescription);
HtmlConverter.convertToPdf(new FileInputStream(htmlLoc), pdf, properties);
```
```
//渲染成桌面应用布局
PageSize pageSize = PageSize.A4.rotate();
```
```
//渲染成平板布局
PageSize pageSize = new PageSize(575, 1500);
```
```
//渲染成智能手机布局
PageSize pageSize = new PageSize(440, 2000);
```
5. 使用pdfhtml创建报表
5.1 将xml数据文件转化为html,然后将对html文件转化为pdf
```
//重点是前端的xml和xsl文件
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer writer = new OutputStreamWriter(baos);
StreamSource xml = new StreamSource(new File(BASEURI+"movie.xml"));
StreamSource xsl = new StreamSource(new File(BASEURI+"movie.xsl"));
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(xsl);
transformer.transform(xml, new StreamResult(writer));
writer.flush();
writer.close();
byte[] res=baos.toByteArray();
HtmlConverter.convertToPdf(new ByteArrayInputStream(res), new FileOutputStream("xmlToHtmlToPdf.pdf"));
```
5.2 使用事件监听添加水印
```
//添加事件监听
IEventHandler handler = new BackgroundListener(pdf, "hello.pdf");
pdf.addEventHandler(PdfDocumentEvent.START_PAGE, handler);
HtmlConverter.convertToPdf(new FileInputStream(htmlLoc), pdf);
```
```
//实现事件监听接口
public class BackgroundListener implements IEventHandler {
PdfXObject stationery;
public BackgroundListener(PdfDocument pdf, String src) throws IOException {
PdfDocument template = new PdfDocument(new PdfReader(src));
PdfPage page = template.getPage(1);
stationery = page.copyAsFormXObject(pdf);
template.close();
}
@Override
public void handleEvent(Event event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfDocument pdf = docEvent.getDocument();
PdfPage page = docEvent.getPage();
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdf);
pdfCanvas.addXObject(stationery, 0, 0);
Rectangle rect = new Rectangle(36, 32, 36, 64);
Canvas canvas = new Canvas(pdfCanvas, pdf, rect);
canvas.add(new Paragraph(String.valueOf(pdf.getNumberOfPages()))
.setFontSize(48)
.setFontColor(ColorConstants.RED));
canvas.close();
}
}
```
5.3 将页面高度大于1页的html存放到1页的pdf中
```
PdfWriter pwriter = new PdfWriter("largeHtmlToOnePdf.pdf");
PdfDocument pdf = new PdfDocument(pwriter);
pdf.setDefaultPageSize(new PageSize(595, 14400));
Document document = HtmlConverter.convertToDocument(new ByteArrayInputStream(res), pdf,null);
EndPosition endPosition = new EndPosition();
LineSeparator separator = new LineSeparator(endPosition);
document.add(separator);
document.getRenderer().close();
//调整单页pdf的高度
PdfPage page = pdf.getPage(1);
float y = endPosition.getY() - 36;
page.setMediaBox(new Rectangle(0, y, 595, 14400 - y));
document.close();
```
5.4 创建特殊类型pdf文档:
```
//注意:需要事先在html中添加字符集,否则报错字体没嵌入
//比如:
PdfWriter writer = new PdfWriter("htmlToPdfA2B.pdf");
PdfADocument pdf = new PdfADocument(writer,
PdfAConformanceLevel.PDF_A_2B,
new PdfOutputIntent("Custom",
"",
"http://www.color.org",
"sRGB IEC61966-2.1",
new FileInputStream("src/main/resources/sRGB_CS_profile.icm")));
HtmlConverter.convertToPdf(new FileInputStream(htmlLoc), pdf);
```
6. 使用自定义的tag标签
6.1 示例:浏览器无法解析该标签,但是pdf可以
```
//html添加一个自定义
标签
this is define name tag
```
```
//后台操作
ConverterProperties converterProperties = new ConverterProperties();
converterProperties.setTagWorkerFactory(new DefaultTagWorkerFactory() {
@Override
public ITagWorker getCustomTagWorker( IElementNode tag, ProcessorContext context) {
if ("name".equalsIgnoreCase(tag.name()) ) {
return new SpanTagWorker(tag, context){
@Override
public boolean processContent(String content, ProcessorContext context) {
return super.processContent("Bruno Lowagie", context);
}
};
}
return null;
}
});
HtmlConverter.convertToPdf(new File(htmlLoc), new File("customtagsToPdf.pdf"), converterProperties);
```
7. 使用自定义的Css样式
7.1 示例: 浏览器无法解析该样式,但是pdf可以
```
//html添加一个自定义样式kleur: groen
```
```
//后台操作
ConverterProperties converterProperties = new ConverterProperties();
converterProperties.setCssApplierFactory(new DefaultCssApplierFactory() {
ICssApplier dutchCssColor = new DutchColorCssApplier();
@Override
public ICssApplier getCustomCssApplier(IElementNode tag) {
if( tag.name().equals(TagConstants.DIV) ){
return dutchCssColor;
}
return null;
}
});
HtmlConverter.convertToPdf(new File(htmlLoc), new File("customCssToPdf.pdf"), converterProperties);
```
```
//实现样式接口
public class DutchColorCssApplier extends BlockCssApplier {
public static final Map KLEUR = new HashMap();
static {
KLEUR.put("groen", "green");
}
@Override
public void apply(ProcessorContext context, IStylesContainer stylesContainer, ITagWorker tagWorker){
Map cssStyles = stylesContainer.getStyles();
if(cssStyles.containsKey("kleur")){
cssStyles.put(CssConstants.COLOR,KLEUR.get(cssStyles.get("kleur")));
stylesContainer.setStyles(cssStyles);
}
super.apply(context, stylesContainer,tagWorker);
}
}
```
8. 在pdfhtml中使用字体
8.1 示例: 后台基本不变,前端htm可以使用14种标准字体,itext附带的12中常规字体,以及系统字体
```
String html = "font_standardtype1.html";
String htmlLoc = BASEURI + html;
HtmlConverter.convertToPdf(new File(htmlLoc), new File("standardType1ToPdf.pdf"));
```
8.2 Web开放字体的使用
```
//当前端需要的字体本机没有时,通过@font-face自动下载,在html页面设置
@font-face {
font-family: "SourceSerifPro-Regular";
src: url("fonts/SourceSerifPro-Regular.otf.woff") format("woff");
}
.regular {
font-family: "SourceSerifPro-Regular";
}
lalalalalalal |
```
8.3 使用指定字体渲染pdf中指定部分,和html呼应
```
//指定单个字体
FontProvider fontProvider = new DefaultFontProvider();
FontProgram fontProgram = FontProgramFactory.createFont(BASEURI+"font/Cardo-Regular.ttf");
fontProvider.addFont(fontProgram);
ConverterProperties properties = new ConverterProperties();
properties.setFontProvider(fontProvider);
HtmlConverter.convertToPdf(new File(htmlLoc), new File("addExtraFontToPdf.pdf"), properties);
```
```
//指定字体目录
FontProvider fontProvider = new DefaultFontProvider();
fontProvider.addDirectory(BASEURI+"/font/");
ConverterProperties properties = new ConverterProperties();
properties.setFontProvider(fontProvider);
HtmlConverter.convertToPdf(new File(htmlLoc), new File("addExtraFontDirToPdf.pdf"), properties);
```
8.4 国际化操作:也是添加对应的字体即可
```
String html = "i18n.html";
String htmlLoc = BASEURI + html;
ConverterProperties properties = new ConverterProperties();
FontProvider fontProvider = new DefaultFontProvider(false, false, false);
String[] fonts = {
"src/main/resources/font/NotoSans-Regular.ttf",
"src/main/resources/font/NotoSans-Bold.ttf",
"src/main/resources/font/NotoSansCJKsc-Regular.otf",
"src/main/resources/font/NotoNaskhArabic-Regular.ttf",
"src/main/resources/font/NotoSansHebrew-Regular.ttf"
};
for (String font : fonts) {
FontProgram fontProgram = FontProgramFactory.createFont(font);
fontProvider.addFont(fontProgram);
}
properties.setFontProvider(fontProvider);
HtmlConverter.convertToPdf(new File(htmlLoc), new File("internationalizationToPdf.pdf"), properties);
```
8.4 解决中文无法显示问题--添加NotoSansCJKsc-Regular.otf字体
```
String html = "chineseGarble.html";
String htmlLoc = BASEURI + html;
ConverterProperties properties = new ConverterProperties();
FontProvider fontProvider = new DefaultFontProvider();
FontProgram fontProgram = FontProgramFactory.createFont(BASEURI+"font/NotoSansCJKsc-Regular.otf");
fontProvider.addFont(fontProgram);
properties.setFontProvider(fontProvider);
HtmlConverter.convertToPdf(new File(htmlLoc), new File("chineseGarbledToPdf.pdf"), properties);
```
9. 注意事项
9.1 如何将ASP或JSP页面转换为PDF?
答:对html的抽象,需要开发者自行将其创建为html。pdfHtml只能解析htm和css
9.2 如何将多个HTML文件解析为一个PDF?
答:第一种:将每个HTML转换为内存中的一个单独的PDF文件。使用pdfmerge将这些文件合并为单个PDF。可能存在中间有大量空格
```
public void createPdf(String baseUri, String[] src, String dest) throws IOException {
ConverterProperties properties = new ConverterProperties();
properties.setBaseUri(baseUri);
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdf = new PdfDocument(writer);
PdfMerger merger = new PdfMerger(pdf);
for (String html : src) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfDocument temp = new PdfDocument(new PdfWriter(baos));
HtmlConverter.convertToPdf(new FileInputStream(html), temp, properties);
temp = new PdfDocument(new PdfReader(new ByteArrayInputStream(baos.toByteArray())));
merger.merge(temp, 1, temp.getNumberOfPages());
temp.close();
}
pdf.close();
}
```
第二种: (推荐--页面更加紧凑) 将不同的HTML文件解析为一系列iText元素。我们将所有这些元素添加到一个PDF文档中。
```
public void createPdf(String baseUri, String[] src, String dest) throws IOException {
ConverterProperties properties = new ConverterProperties();
properties.setBaseUri(baseUri);
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf);
for (String html : src) {
List elements =
HtmlConverter.convertToElements(new FileInputStream(html), properties);
for (IElement element : elements) {
document.add((IBlockElement)element);
}
}
document.close();
}
```
9.3 可以从URL生成PDF而不是从磁盘上的文件?
答:
```
createPdf(new URL("https://stackoverflow.com/help/on-topic"), DEST);
public void createPdf(URL url, String dest) throws IOException {
HtmlConverter.convertToPdf(url.openStream(), new FileOutputStream(dest));
}
```