java - 字体未加载/未找到 Apache fop 2.3

标签 java pdf xslt servlets apache-fop

我已更新apache fop版本来自 1.12.3 ,现在我遇到了与自定义字体相关的问题,我正在尝试从作为 war 文件的一部分部署的字体目录加载字体,它在 1.1 版本中工作正常。

出现错误

SEVERE: org.xml.sax.SAXParseException; systemId: jndi:/localhost/fileprocessor/stylesheets/mainpage_invoice.xsl; lineNumber: 104; columnNumber: 53; java.lang.RuntimeException: Failed to read font file CALIBRI.TTF
Apr 08, 2019 2:57:25 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [fileprocessor] in context with path [/fileprocessor] threw exception [javax.xml.transform.TransformerException: java.lang.RuntimeException: Failed to read font file CALIBRI.TTF] with root cause
java.lang.NullPointerException

配置文件:

<!-- Strict user configuration -->
<strict-configuration>true</strict-configuration>

<!-- Strict FO validation -->
<strict-validation>true</strict-validation>

<!-- Base URL for resolving relative URLs -->
<base>servlet-context:/</base>

<!-- Font Base URL for resolving relative font URLs -->
<font-base>servlet-context:/fonts/</font-base>

<!-- Source resolution in dpi (dots/pixels per inch) for determining the size of pixels in SVG and bitmap images, default: 72dpi -->
<source-resolution>300</source-resolution>
<!-- Target resolution in dpi (dots/pixels per inch) for specifying the target resolution for generated bitmaps, default: 72dpi -->
<target-resolution>300</target-resolution>

<renderers>
    <renderer mime="application/pdf">
        <fonts>             
            <font embed-url="glypha_lt_35_thin.ttf">            <font-triplet name="glypha" style="normal" weight="100"/></font>
            <font embed-url="glypha_lt_35_thin_oblique.ttf">    <font-triplet name="glypha" style="italic" weight="100"/></font>
            <font embed-url="glypha_lt_45_light.ttf">           <font-triplet name="glypha" style="normal" weight="300"/></font>
            <font embed-url="glypha_lt_45_light_oblique.ttf">   <font-triplet name="glypha" style="italic" weight="300"/></font>
            <font embed-url="glypha_lt_55_roman.ttf">           <font-triplet name="glypha" style="normal" weight="400"/></font>
            <font embed-url="glypha_lt_55_oblique.ttf">         <font-triplet name="glypha" style="italic" weight="400"/></font>
            <font embed-url="glypha_lt_65_bold.ttf">            <font-triplet name="glypha" style="normal" weight="700"/></font>
            <font embed-url="glypha_lt_65_bold_oblique.ttf">    <font-triplet name="glypha" style="italic" weight="700"/></font>
            <font embed-url="glypha_lt_75_black.ttf">           <font-triplet name="glypha" style="normal" weight="900"/></font>
            <font embed-url="glypha_lt_75_black_oblique.ttf">   <font-triplet name="glypha" style="italic" weight="900"/></font>

            <font embed-url="courier.ttf">                      <font-triplet name="courier" style="normal" weight="400"/></font>
            <font embed-url="courier_bold.ttf">                 <font-triplet name="courier" style="normal" weight="700"/></font>
            <font embed-url="courier_bold_italic.ttf">          <font-triplet name="courier" style="italic" weight="700"/></font>
            <font embed-url="courier_italic.ttf">               <font-triplet name="courier" style="italic" weight="400"/></font>


            <font embed-url="CALIBRI.TTF">                      <font-triplet name="calibri" style="normal" weight="400"/></font>
            <font embed-url="CALIBRIB.TTF">                     <font-triplet name="calibri" style="normal" weight="700"/></font>
            <font embed-url="CALIBRII.TTF">                     <font-triplet name="calibri" style="italic" weight="700"/></font>
            <font embed-url="CALIBRIZ.TTF">                     <font-triplet name="calibri" style="italic" weight="400"/></font>


        </fonts>
    </renderer>
</renderers>

文件处理器类:

public class fileprocessor extends HttpServlet {
    private static final long serialVersionUID = 1L;
    protected URIResolver uriResolver;
    private FopFactory fopFactory;
    private TransformerFactory factory;
    private FopFactoryBuilder fopFactoryBuilder;
    private ResourceResolver resolver;

    public static InputSource sourceToInputSource(StreamSource ss) throws ServletException {
        InputSource isource = new InputSource(ss.getSystemId());
        isource.setByteStream(ss.getInputStream());
        isource.setCharacterStream(ss.getReader());
        isource.setPublicId(ss.getPublicId());
        return isource;
    }
    class MyErrorListener implements ErrorListener{
        @Override
        public void error(TransformerException arg0)
                throws TransformerException {
            throw arg0;
        }
        @Override
        public void fatalError(TransformerException arg0)
                throws TransformerException {
            throw arg0;
        }
        @Override
        public void warning(TransformerException arg0)
                throws TransformerException {
            throw arg0;
        }
    };

    @Override
    public void init() throws ServletException {
        this.uriResolver = new ServletContextURIResolver(getServletContext());

        factory = TransformerFactory.newInstance();
        factory.setURIResolver(this.uriResolver);
        factory.setErrorListener(new MyErrorListener());

        this.resolver = new ResourceResolver() {

            @Override
            public Resource getResource(URI uri) throws IOException {               
                return new Resource(getServletContext().getResourceAsStream(uri.toASCIIString()));
            }

            @Override
            public OutputStream getOutputStream(URI uri) throws IOException {
                URL url = getServletContext().getResource(uri.toASCIIString());
                return url.openConnection().getOutputStream();
            }
        };


        try {
            Source s = this.uriResolver.resolve("servlet-context:/configuration.xml", null);

            DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
            Configuration cfg = cfgBuilder.build(sourceToInputSource((StreamSource)s));



            fopFactoryBuilder = new FopFactoryBuilder(new File(".").toURI(), resolver).setConfiguration(cfg);

            this.fopFactory = fopFactoryBuilder.build();



        } catch (SAXException e) {
            throw new ServletException("error",e);
        } catch (IOException e) {
            throw new ServletException("error",e);
        } catch (ConfigurationException e) {
            throw new ServletException("error",e);
        } catch (TransformerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

    public fileprocessor() {
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            String uri=request.getRequestURI().substring(request.getContextPath().length());


             if (uri.equals("/invoice/pdf")) {
                // base stylesheet mainpage_invoice.xsl where i am using font
                Source xslt = uriResolver.resolve("servlet-context:/stylesheets/mainpage_invoice.xsl", null);
                Transformer transformer = factory.newTransformer(xslt);
                transformer.setURIResolver(this.uriResolver);               
                transformer.setParameter("draft", false);
                transformer.setErrorListener(new MyErrorListener());

                String xmlInput = CharStreams.toString(request.getReader());

                Source src = new StreamSource(new StringReader(xmlInput));
                response.setContentType("application/pdf");
                Fop fop = this.fopFactory.newFop(MimeConstants.MIME_PDF, response.getOutputStream());
                Result res = new SAXResult(fop.getDefaultHandler());
                transformer.transform(src, res);            
            } else {
                response.sendError(404);
            }
        } catch (Exception e) {             
            throw new ServletException(e);
        }
    }

}

最佳答案

为了解决这个问题,我更新了我的 init 方法,如下所示:

public void init() throws ServletException {
    this.uriResolver = new ServletContextURIResolver(getServletContext());

    factory = TransformerFactory.newInstance();
    factory.setURIResolver(this.uriResolver);
    factory.setErrorListener(new MyErrorListener());

    this.resolver = new ResourceResolver() {

        @Override
        public Resource getResource(URI uri) throws IOException {
            /* Check for font file and prepend font dir as resource resolver can not resolve with out it */             

            String Prepend = File.separator + File.separator + "fonts" + File.separator + File.separator;

            String ext = FilenameUtils.getExtension(Paths.get(uri).getFileName().toString()); 
            if (ext.equalsIgnoreCase("TTF")) {
                return new Resource(getServletContext().getResourceAsStream( Prepend + Paths.get(uri).getFileName().toString()));                   
            }else {
                return new Resource(getServletContext().getResourceAsStream(uri.toASCIIString()));
            }
        }

        @Override
        public OutputStream getOutputStream(URI uri) throws IOException {
            URL url = getServletContext().getResource(uri.toASCIIString());
            return url.openConnection().getOutputStream();
        }
    };

    try {
        Source s = this.uriResolver.resolve("servlet-context:/configuration.xml", null);
        DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
        Configuration cfg = cfgBuilder.build(sourceToInputSource((StreamSource)s));

        this.fopFactoryBuilder = new FopFactoryBuilder(new File(".").toURI(), resolver).setConfiguration(cfg);
        this.fopFactory = fopFactoryBuilder.build();


    } catch (SAXException e) {
        throw new ServletException("error",e);
    } catch (IOException e) {
        throw new ServletException("error",e);
    } catch (TransformerException e) {
        throw new ServletException("error",e);
    } catch (ConfigurationException e) {
        throw new ServletException("error",e);
    }

}

关于java - 字体未加载/未找到 Apache fop 2.3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55574468/

相关文章:

java - Java中如何操作数组?

pdf - 是否可以在 Cassandra 中以 CQL blob 类型存储 PDF 文件?

java - 使用 itext5 将文本添加到 PDF 中的矩形

html - 编写希腊语 Rmarkdown pdf 或 html 文档

java - JRadioButton 正在选择最后一个

java - openejb 嵌入式容器找不到 persistence.xml

javascript - 使用 Greasemonkey 脚本将 javascript 添加到使用 XSLT 转换的 XML 文件

xslt - 使用 XSLT 为 umbraco 创建多级菜单?

xml - XSLT 1.0 获取当前日期时间

java - 无法将我的 Spring boot 应用程序打包为可运行的 fat Jar