2010-03-04 42 views
5

我正在使用Flying Saucer将某些PDF文档从字符串呈现为XHTML。我的代码是这样的:Flying Saucer XHTML中的相对路径?

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

我试图理解的是,使用这种方法,其中在XHTML的相对路径没有得到解决的时候?例如,对于图像或样式表。我能够使用此方法成功生成基于文本的文档,但我需要了解如何引用我的图像和CSS。

回答

14

setDocument()方法有两个参数:document和url。 url参数指示用于预先添加到xhtml中出现的相对路径的基本url,如img标记。

假设你有:

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

现在假设 “图像” 位于文件夹:

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

您可以使用setDocument()为:

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

注意的尾随斜线,没有它就无法工作。

这是它为我工作的方式。我假设你可以使用其他类型的网址,例如“http:// ...”。

0

您可以有文件路径,这应该是绝对路径,或http:// url。相对路径可以工作,但不是可移植的,因为它取决于你运行程序的目录是从

1

AtilaUy的答案是在飞碟的默认工作方式。

更一般的答案是它要求UserAgentContext。当文档被设置时,它将在UserAgentContext上调用setBaseURL()。然后,当它想要读取实际资源数据时,它将调用resolveURL()来解析相对URL并最终resolveAndOpenStream()。

嗯,这个答案对你来说可能是太晚了,无论如何,但我需要这样的答案时,我设置了,并设置自定义用户代理上下文是我最终使用的解决方案。

5

本周我为此工作,我给你什么对我很好。

在现实生活中,您的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(); 

干杯。

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的答案,这看起来相当有效在大多数情况下)。

这是我如何做一个XHTMLPane使用动态生成的样式表:

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. 

    } ; 
} 

然后,我用它这样的:

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

对我来说,最好的解决办法是:

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

然后所有提供的HTML样式和图像(如

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

)按预期呈现。

+0

这必须是基于Spring的解决方案。 –