9

Flying Saucer を使用して、一部の PDF ドキュメントを文字列から XHTML にレンダリングしています。私のコードは次のようなものです:

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

私が理解しようとしているのは、この方法を使用する場合、XHTML の相対パスはどこから解決されるのでしょうか? たとえば、画像やスタイルシートの場合です。この方法を使用してテキストベースのドキュメントを正常に生成できますが、画像と CSS を参照する方法を理解する必要があります。

4

7 に答える 7

20

setDocument() メソッドは、document と url の 2 つのパラメーターを取ります。url パラメーターは、img タグなど、xhtml に表示される相対パスの前に追加するために使用されるベース URL を示します。

あなたが持っていると仮定します:

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

ここで、「images」フォルダが次の場所にあるとします。

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

setDocument() を次のように使用できます。

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

末尾のスラッシュに注意してください。これがないと機能しません。

これが私にとってはうまくいった方法です。「http://...」など、他のタイプの URL を使用できると思います。

于 2011-01-07T17:25:36.100 に答える
8

今週、私はこれに取り組みました。

実際には、XHTML ドキュメントは複数のリソース (画像、css など) を相対パスで指しています。また、フライングソーサーにそれらを見つける場所を説明する必要があります。それらは、クラスパスまたはファイル システムにあります。(それらがネットワーク上にある場合は、ベース 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();

乾杯。

于 2013-02-15T13:26:50.540 に答える
2

私にとって最良の解決策は次のとおりです。

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>

) 期待どおりにレンダリングされました。

于 2016-06-15T17:05:42.833 に答える
1

AtilaUy の答えは、Flying Saucer でのデフォルトの動作にぴったりです。

より一般的な答えは、UserAgentContext に問い合わせるというものです。ドキュメントが設定されると、UserAgentContext で setBaseURL() が呼び出されます。次に、相対 URL を解決するために resolveURL() が呼び出され、実際のリソース データを読み取る必要がある場合は、最終的に resolveAndOpenStream() が呼び出されます。

まあ、この答えはおそらくあなたがそれを利用するには遅すぎるでしょうが、私が着手したときにこのような答えが必要でした.カスタムユーザーエージェントコンテキストを設定することは私が最終的に使用した解決策です.

于 2011-04-19T03:22:28.463 に答える
0

もっと簡単なアプローチは次のようになると思います:

                DomNodeList<DomElement> images = result.getElementsByTagName("img");
                for (DomElement e : images) { 
                    e.setAttribute("src", result.getFullyQualifiedUrl(e.getAttribute("src")).toString());
                }
于 2014-07-30T14:42:03.490 に答える
0

パスを解決する別の方法は overrideUserAgentCallback#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() ) ;
于 2015-10-26T08:07:29.713 に答える
0

ファイル パスは絶対パスにするか、http:// URL にすることができます。相対パスは機能しますが、プログラムを実行したディレクトリに依存するため、移植できません

于 2011-03-16T15:27:41.077 に答える