代码之家  ›  专栏  ›  技术社区  ›  Adam Burley

飞碟XHTML中的相对路径?

  •  6
  • Adam Burley  · 技术社区  · 14 年前

    我使用飞碟将一些pdf文档从字符串呈现到xhtml。我的代码是这样的:

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

    我试图理解的是,当使用此方法时,xhtml中的相对路径从何处解析?例如,对于图像或样式表。我可以使用这种方法成功地生成基于文本的文档,但我需要了解如何引用我的图像和css。

    7 回复  |  直到 8 年前
        1
  •  16
  •   AtilaUy    14 年前

    setdocument()方法接受两个参数:document和url。 url参数指示用于在xhtml中(如img标记中)出现的相对路径前面加上前缀的基url。

    假设你有:

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

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

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

    可以将setdocument()用作:

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

    注意后面的斜杠,没有它就不行。

    这就是我的工作方式。我假设您可以使用其他类型的url,比如“http://…”。

        2
  •  7
  •   Remy    11 年前

    这周我做了这件事,我给了你对我有用的东西。

    在现实生活中,xhtml文档指向具有相对路径的多个资源(图像、css等)。 你还得向飞碟解释在哪里能找到它们。它们可以在类路径中,也可以在文件系统中。(如果它们在网络上,您可以只设置基本URL,因此这不会有帮助)

    所以你必须像这样扩展itextureagent:

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

    干杯。

        3
  •  1
  •   Hakanai    13 年前

    阿蒂劳伊的答案是正确的,因为在飞碟的默认工作方式。

    更一般的答案是它会询问useragentcontext。在中设置文档时,它将对useragentContext调用setbaseUrl()。然后它将调用resolveUrl()来解析相对URL,并在它想要读取实际资源数据时最终调用resolveAndOpenStream()。

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

        4
  •  0
  •   Henley Wing Chiu    13 年前

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

        5
  •  0
  •   amrdeus    10 年前

    我认为更简单的方法是:

                    DomNodeList<DomElement> images = result.getElementsByTagName("img");
                    for (DomElement e : images) { 
                        e.setAttribute("src", result.getFullyQualifiedUrl(e.getAttribute("src")).toString());
                    }
    
        6
  •  0
  •   Laurent Caillette    9 年前

    解析路径的另一种方法是重写 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() ) ;
    
        7
  •  0
  •   Irina    8 年前

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

    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>
    

    )按预期呈现。

    推荐文章