首页 > 解决方案 > 字体未加载/未找到 Apache fop 2.3

问题描述

我已将apache fop版本从1.1更新到2.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);
        }
    }

}

标签: javapdfxsltservletsapache-fop

解决方案


为了解决这个问题,我更新了我的 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);
    }

}

推荐阅读