开发者

FOP: how to specify image src relative path?

This is my first question here, i hope i'm doing it right. Sorry for my bad English in advance :)

I am using JSF 2.0 (Eclipse IDE) and i'm trying to generate some PDF files using Apache FOP 1.0.

I was able to make simple PDF files using instructions on Apache Fop site , but i can't insert any image from my application folder. My folder structure is like this: In my application WebContent i have (among else) pdf_transform/xslt/transformFile.xsl, and pdf_transform/xslt/logo.jpg

In transformFile.xsl i have

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

but when i clik 'showPDF' button in my servlet, i get PDF file without image (everything else is there), and this messages in console:

SEVERE: The Source that was returned from URI resolution didn't contain an InputStream for URI: logo.jpg Nov 18, 2010 5:16:49 PM org.apache.fop.events.LoggingEventListener processEvent SEVERE: Image not found. URI: logo.jpg. (No context info available)

I tried to use 'logo.jpg' instead of url('logo.jpg'), putting image on various places inside WebContent folder and using different navigation("./logo.jpg") but it didnt work.

It works fine if i set absolute path (for example "d:/fop/images/logo.jpg") but i need resurces whitin my application.

While searching, i found that this is related to fopFactory.setURIResolver() and/or userAgent.setBaseURL(). Tried something with that, but did开发者_开发知识库nt succeed.

I am new to both JSF and FOP, and this image situation has been bothering me quite a while. Can someone help me with this, or at least direct me to some tutorial on "how to configure FOP for relative path use"?

EDIT: I don't want any absolute paths and app should work independently of its location on computer (to be publishable). My search tells me it has something to do with configuring FOP, but i don't know how to do it :)

Thanks in advance.

P.S. This is method which is called to display 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();
}


i found solution to my problem. I thought i tried that, but it seems i made some little mistake back then. Anyway, with the following code

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

you can access your images (and other resources) from your xslt file using relative path starting from your application's WebContent folder. In my case, i can access logo.jpg like this

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

Took me time to figure out this, i don't get it why no examples with such basic thing on the net (or i can't find them :)

Note: In FOP 2.0 there is no setBaseURL() method. Instead you pass the base URL as a parameter to FopFactory.newInstance(). Many of the other setters have been moved to FopFactoryBuilder.


If you have access to the web url for the pictures you can use that as well when generating reports, ie http://localhost/images/logo.jpg .

But while I still had images locally on the web server, I included the path to the application in the XML file and used it like this:

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

Where the XML structure might be something like this:

<?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>


I had the same problem and tried this solution:

    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);

Then, on XSL I used:

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

To test if this is working, you should be able to see the image on protocol://link:port/img/image.png

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜