我目前正在开发一种可以接受 HTML 输入并将其转换为有效 PDF/A 文件的方法。我知道如何使用 iText(参考:http: //itextsupport.com/download/pdfa3.html )以编程方式构建有效的 PDF/A 文件,但我无法使用 HTML 作为输入和使用生成有效的 PDF/A 文件XMLWorker 将此输入转换为 PDF 文件。我现在遇到的问题是由于 PDF/A 格式的嵌入字体要求。我总是得到这个例外:
线程“main”com.itextpdf.text.pdf.PdfAConformanceException 中的异常:必须嵌入所有字体。这不是:Helvetica
我尝试通过 CSS 文件强制 HTML 输入将使用哪些字体,并通过 XMLWorkerFontProvider 类在输出 PDF 文件中注册要使用的字体,但似乎我做错了什么,因为上面评论的异常总是抛出。
为了让 XMLWorker 使用通过 XMLWorkerFontProvider 类注册的字体,我还需要什么?我想避免在输入中存在的每个 HTML 元素中使用默认字体 Helvetica。
以下是我用于测试的代码:
style.css(只有 1 行):
* { font: normal 100% Arial, sans-serif !important; }
主.java:
package com.itextpdf;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.ICC_Profile;
import com.itextpdf.text.pdf.PdfAConformanceLevel;
import com.itextpdf.text.pdf.PdfAWriter;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.css.CssFile;
import com.itextpdf.tool.xml.css.StyleAttrCSSResolver;
import com.itextpdf.tool.xml.html.CssAppliers;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
StringBuffer buf = new StringBuffer();
buf.append("<!DOCTYPE html>");
buf.append("<html>");
buf.append("<head>");
buf.append("<title>Test</title>");
buf.append("</head>");
buf.append("<body>");
buf.append("<p>This is a test</p>");
buf.append("</body>");
buf.append("</html>");
OutputStream file = null;
Document document = null;
PdfAWriter writer = null;
try {
file = new FileOutputStream(new File("C:\\Users\\amartin\\Desktop\\Test.pdf"));
document = new Document();
writer = PdfAWriter.getInstance(document, file, PdfAConformanceLevel.PDF_A_1B);
// Create XMP metadata. It's a PDF/A requirement.
writer.createXmpMetadata();
document.open();
// Set output intent. PDF/A requirement.
ICC_Profile icc = ICC_Profile.getInstance(new FileInputStream("./src/main/resources/com/itextpdf/sRGB Color Space Profile.icm"));
writer.setOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc);
// CSS
CSSResolver cssResolver = new StyleAttrCSSResolver();
CssFile cssFile = XMLWorkerHelper.getCSS(new FileInputStream("./css/style.css"));
cssResolver.addCss(cssFile);
XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider();
fontProvider.register("./fonts/arial.ttf");
fontProvider.register("./fonts/sans-serif.ttf");
fontProvider.addFontSubstitute("lowagie", "garamond");
CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
// Pipelines
PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
XMLWorker worker = new XMLWorker(css, true);
XMLParser p = new XMLParser(worker);
Reader reader = new StringReader(buf.toString());
p.parse(reader);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (document != null && document.isOpen())
document.close();
try {
if (file != null)
file.close();
} catch (IOException e) {}
if (writer != null && !writer.isCloseStream())
writer.close();
}
}
}
编辑:
作为对 Bruno 的回答,我扩展了 FontFactoryImp 类,覆盖了 getFont() 方法(具有所有参数的方法)。它像这样调用 System.out.println 函数:
System.out.println("=fontname: " + fontname + " =encoding: " + encoding + " =embedded : " + embedded + " =size: " + size + " =style: " + style + " =BaseColor: " + color)
然后使用相同的参数调用 parent.getFont() 方法。我看到的唯一输出是:
=fontname: null =encoding: Cp1252 =embedded: true =size: -1.0 =style: -1 =BaseColor: null =fontname: null =encoding: Cp1252 =embedded: true =size: -1.0 =style: -1 =BaseColor : 无效的
并抛出异常,粘贴在此代码之前。