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的解決方案。 –