Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 飞碟XHTML中的相对路径?_Java_Xhtml_Pdf Generation_Flying Saucer - Fatal编程技术网

Java 飞碟XHTML中的相对路径?

Java 飞碟XHTML中的相对路径?,java,xhtml,pdf-generation,flying-saucer,Java,Xhtml,Pdf Generation,Flying Saucer,我正在使用飞碟将一些PDF文档从字符串渲染到XHTML。我的代码类似于: iTextRenderer.setDocument(documentGenerator.generate(xhtmlDocumentAsString)); iTextRenderer.layout(); iTextRenderer.createPDF(outputStream); 我试图理解的是,当使用此方法时,XHTML中的相对路径从何处解析?例如,对于图像或样式表。我能够使用此方法成功生成基于文本的文档,但我需要了解

我正在使用飞碟将一些PDF文档从字符串渲染到XHTML。我的代码类似于:

iTextRenderer.setDocument(documentGenerator.generate(xhtmlDocumentAsString));
iTextRenderer.layout();
iTextRenderer.createPDF(outputStream);
我试图理解的是,当使用此方法时,XHTML中的相对路径从何处解析?例如,对于图像或样式表。我能够使用此方法成功生成基于文本的文档,但我需要了解如何引用图像和CSS。

setDocument()方法采用两个参数:document和url。 url参数表示用于在xhtml中显示的相对路径(例如在img标记中)前加前缀的基本url

假设你有:

<img src="images/img1.jpg">
您可以将setDocument()用作:

注意后面的斜杠,没有它就不能工作


这就是我的工作方式。我想您可以使用其他类型的URL,例如“http://...“

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

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

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


好吧,这个答案对你来说可能太晚了,你根本无法使用它,但我在出发时需要这样一个答案,而设置自定义用户代理上下文是我最终使用的解决方案。

本周我做了这个,我给你一个对我来说很好的答案

在现实生活中,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();
你是这样使用它的:

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

干杯。

我认为更简单的方法是:

                DomNodeList<DomElement> images = result.getElementsByTagName("img");
                for (DomElement e : images) { 
                    e.setAttribute("src", result.getFullyQualifiedUrl(e.getAttribute("src")).toString());
                }
domandelistimages=result.getElementsByTagName(“img”);
对于(DomElement e:images){
e、 setAttribute(“src”,result.getFullyQualifiedUrl(e.getAttribute(“src”)).toString();
}

解析路径的另一种方法是重写
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.

  } ;
}

对我来说,最好的解决方案是:

renderer.setDocumentFromString(htmlContent,  new ClassPathResource("/META-INF/pdfTemplates/").getURL().toExternalForm());
然后所有提供的样式和图像都是html格式的(如



)按预期呈现

这必须是基于Spring的解决方案。如果我们有一个RestController,这能工作吗?我假设您正在将所有CSS和图像放在静态目录下。指定
文件://
前缀很重要,因为FS查找的是URL,而不是路径。它不能只处理以
C://
/some/absolute/path
开头的路径。
renderer.setDocumentFromString(htmlContent,  new ClassPathResource("/META-INF/pdfTemplates/").getURL().toExternalForm());
<img class="logo" src="images/logo.png" />
<link rel="stylesheet" type="text/css" media="all" href="css/style.css"></link>