Relative paths in Flying Saucer XHTML?

I use Flying Saucer to render some PDF documents from strings in XHTML. My code looks something like this:

iTextRenderer.setDocument(documentGenerator.generate(xhtmlDocumentAsString));
iTextRenderer.layout();
iTextRenderer.createPDF(outputStream);

What I'm trying to understand is to use this method in which relative paths are allowed in XHTML? For example, for images or style sheets. I can use this method to successfully create a text document, but I need to understand how to reference my images and CSS.

+5
source share
7 answers

setDocument() : document url. url url, , xhtml, , img.

, :

<img src="images/img1.jpg">

, "images" :

C:/physical/route/to/app/images/

setDocument() :

renderer.setDocument(xhtmlDoc, "file:///C:/physical/route/to/app/");

, .

. , URL-, "http://...".

+14

, , .

XHTML (, css ..) . Flying Saucer, . . ( , url, )

, ITextUserAgent :

private static class ResourceLoaderUserAgent extends ITextUserAgent {

    public ResourceLoaderUserAgent(ITextOutputDevice outputDevice) {
        super(outputDevice);
    }

    protected InputStream resolveAndOpenStream(String uri) {

        InputStream is = super.resolveAndOpenStream(uri);
        String fileName = "";
        try {
            String[] split = uri.split("/");
            fileName = split[split.length - 1];
        } catch (Exception e) {
            return null;
        }

        if (is == null) {
            // Resource is on the classpath
            try{
                is = ResourceLoaderUserAgent.class.getResourceAsStream("/etc/images/" + fileName);
            } catch (Exception e) {
        }

        if (is == null) {
            // Resource is in the file system
            try {
                is = new FileInputStream(new File("C:\\images\\" + fileName));
            } catch (Exception e) {
            }
        }

        return is;
    }
}

:

// Output stream containing the result
ByteArrayOutputStream baos = new ByteArrayOutputStream();

ITextRenderer renderer = new ITextRenderer();
ResourceLoaderUserAgent callback = new ResourceLoaderUserAgent(renderer.getOutputDevice());
callback.setSharedContext(renderer.getSharedContext());
renderer.getSharedContext().setUserAgentCallback(callback);

renderer.setDocumentFromString(htmlSourceAsString);

renderer.layout();
renderer.createPDF(baos);
renderer.finishPDF();

.

+5

AtilaUy - , Flying Saucer.

, UserAgentContext. setBaseURL() UserAgentContext, . resolveURL(), URL- AndOpenStream(), .

, , , , , , , - , .

+1

, , http://urls. , , ,

0

, :

                DomNodeList<DomElement> images = result.getElementsByTagName("img");
                for (DomElement e : images) { 
                    e.setAttribute("src", result.getFullyQualifiedUrl(e.getAttribute("src")).toString());
                }
0

- UserAgentCallback#resolveURI, , URL ( AtilaUy, ).

Here's how I do XHTMLPaneusing dynamically created style sheets:

public static UserAgentCallback interceptCssResourceLoading(
    final UserAgentCallback defaultAgentCallback,
    final Map< URI, CSSResource > cssResources
) {
  return new UserAgentCallback() {
    @Override
    public CSSResource getCSSResource( final String uriAsString ) {
      final URI uri = uriQuiet( uriAsString ) ; // Just rethrow unchecked exception.
      final CSSResource cssResource = cssResources.get( uri )  ;
      if( cssResource == null ) {
        return defaultAgentCallback.getCSSResource( uriAsString ) ;
      } else {
        return cssResource ;
      }
    }

    @Override
    public String resolveURI( final String uriAsString ) {
      final URI uri = uriQuiet( uriAsString ) ;
      if( cssResources.containsKey( uri ) ) {
        return uriAsString ;
      } else {
        return defaultAgentCallback.resolveURI( uriAsString ) ;
      }
    }

    // Delegate all other methods to defaultUserAgentCallback.

  } ;
}

Then I use it as follows:

  final UserAgentCallback defaultAgentCallback =
      xhtmlPanel.getSharedContext().getUserAgentCallback() ;
  xhtmlPanel.getSharedContext().setUserAgentCallback(
      interceptCssResourceLoading( defaultAgentCallback, cssResources ) ) ;
  xhtmlPanel.setDocumentFromString( xhtml, null, new XhtmlNamespaceHandler() ) ;
0
source

The best solution for me was:

renderer.setDocumentFromString(htmlContent,  new ClassPathResource("/META-INF/pdfTemplates/").getURL().toExternalForm());

Then all the provided styles and images in html (e.g.

<img class="logo" src="images/logo.png" />
<link rel="stylesheet" type="text/css" media="all" href="css/style.css"></link>

) displayed as expected.

0
source

All Articles