【问题标题】:FOP: how to specify image src relative path?FOP:如何指定图像 src 相对路径?
【发布时间】:2011-05-12 04:15:45
【问题描述】:

这是我在这里的第一个问题,我希望我做对了。抱歉我的英语不好:)

我正在使用 JSF 2.0 (Eclipse IDE),我正在尝试使用 Apache FOP 1.0 生成一些 PDF 文件。

我能够使用 Apache Fop site 上的说明制作简单的 PDF 文件,但我无法从我的应用程序文件夹中插入任何图像。我的文件夹结构是这样的: 在我的应用程序 WebContent 中,我有(除其他外) pdf_transform/xslt/transformFile.xsl,和 pdf_transform/xslt/logo.jpg

在 transformFile.xsl 我有

<fo:block><fo:external-graphic src="url('logo.jpg')"/></fo:block>

但是当我在我的 servlet 中单击“showPDF”按钮时,我得到没有图像的 PDF 文件(其他所有内容都在那里),并且在控制台中显示此消息:

SEVERE:返回的源 来自 URI 解析不包含 URI 的 InputStream:logo.jpg 11 月 18 日, 2010 下午 5:16:49 org.apache.fop.events.LoggingEventListener processEvent 严重:找不到图像。 URI:徽标.jpg。 (没有上下文信息 可用)

我尝试使用 'logo.jpg' 而不是 url('logo.jpg'),将图像放在 WebContent 文件夹内的各个位置并使用不同的导航(“./logo.jpg”),但它没有用。

如果我设置绝对路径(例如“d:/fop/images/logo.jpg”),它可以正常工作,但我需要在我的应用程序中使用资源。

在搜索时,我发现这与 fopFactory.setURIResolver() 和/或 userAgent.setBaseURL() 有关。尝试了一些东西,但没有成功。

我是 JSF 和 FOP 的新手,这种图像问题困扰了我很长一段时间。有人可以帮我解决这个问题,或者至少指导我阅读一些关于“如何配置 FOP 以使用相对路径”的教程?

编辑:我不希望任何绝对路径和应用程序应该独立于其在计算机上的位置工作(可发布)。我的搜索告诉我这与配置 FOP 有关,但我不知道该怎么做 :)

提前致谢。

附:这是调用显示 PDF 的方法:

public void printExchangeRateList(ActionEvent event) {

    BufferedOutputStream output = null;

    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();  

    String path = externalContext.getRealPath("/");


    try {

        response.reset();
        response.setHeader("Content-Type", "application/pdf");
        output = new BufferedOutputStream(response.getOutputStream(), 10240);

        File xsltfile = new File(path+"/pdf_transform/xslt/transformFile.xsl");

        FopFactory fopFactory = FopFactory.newInstance();
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        try {
            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, output);

            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer(new StreamSource(xsltfile));

            Source src = new DOMSource(makeXML()); // my method
            Result res = new SAXResult(fop.getDefaultHandler());

            transformer.transform(src, res);


        } finally {
            if (output != null) output.close();
            /*try {
                out.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }*/
        }

    } catch (Exception e) {
        // TODO Auto-generated catch block
    }

    facesContext.responseComplete();
}

【问题讨论】:

    标签: jsf-2 relative-path apache-fop


    【解决方案1】:

    我找到了解决问题的方法。我以为我试过了,但当时我似乎犯了一些小错误。无论如何,使用以下代码

    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    String basePath = externalContext.getRealPath("/");
    
    FopFactory fopFactory = FopFactory.newInstance();
    fopFactory.setBaseURL(basePath);
    FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
    foUserAgent.setBaseURL(fopFactory.getBaseURL());
    
    Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, output); // for some output
    

    您可以使用从应用程序的 WebContent 文件夹开始的相对路径从 xslt 文件访问您的图像(和其他资源)。就我而言,我可以像这样访问 logo.jpg

    <fo:external-graphic src="url('pdf_transform/xslt/logo.jpg')"/>
    

    我花了一些时间才弄清楚这一点,我不明白为什么网上没有这样基本的例子(或者我找不到它们:)

    注意:在 FOP 2.0 中没有 setBaseURL() 方法。相反,您将基本 URL 作为参数传递给FopFactory.newInstance()。许多其他二传手已移至FopFactoryBuilder

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题并尝试了这个解决方案:

          FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
          Request request = RequestCycle.get().getRequest();
          //sort of a hack to find the path to the files that are in /img folder.
          String baseUrl = request.getUrl().getProtocol()+"://"+request.getUrl().getHost()+":"+request.getUrl().getPort();  
          foUserAgent.setBaseURL(baseUrl);
      

      然后,我在 XSL 上使用:

      <fo:external-graphic src="/img/image.png" />
      

      要测试这是否有效,您应该能够在 protocol://link:port/img/image.png 上看到图像

      【讨论】:

        【解决方案3】:

        如果您可以访问图片的网址,您也可以在生成报告时使用它,即http://localhost/images/logo.jpg

        但是,虽然我仍然在 Web 服务器上本地拥有图像,但我在 XML 文件中包含了应用程序的路径并像这样使用它:

        <xsl:variable name="base_path" select="base-path"/>
        <xsl:variable name="logo" select="companies/company/logo"/>
        <fo:external-graphic src="url({$base_path}{logo})"/>
        

        XML 结构可能是这样的:

        <?xml version="1.0" encoding="UTF-8"?>
        <base-path>/path/to/app/</base-path>
        <companies>
          <company>
            <logo>images/company1.jpg</logo>
          </company>
          <company>
            <logo>images/company2.jpg</logo>
          </company>
        </companies>
        

        【讨论】:

        • 感谢您的回答。但这不是我要找的。当您制作 xml 时,“/path/to/app/”字符串必须看起来像“C:\Eclipse\workspace\myProject\.. etc”(如果我做对了)。我使此应用程序可发布,并且我访问的所有 xml 数据和图像必须在应用程序范围内引用(抱歉,我的问题中没有明确写出,我现在将对其进行编辑)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-15
        • 1970-01-01
        • 2012-01-02
        相关资源
        最近更新 更多