2011-01-24 9 views
6

Uso il Flying Saucer per creare un pdf da xhtml, ospitato su un server tomcat. La maggior parte delle immagini incluse nel pdf sono disponibili pubblicamente (loghi e così via), ma alcune di esse sono protette da un login (cioè, sono trasmesse attraverso un servlet se l'utente ha effettuato l'accesso).Risoluzione delle risorse protette con Flying Saucer (ITextRenderer)

Quando si incolla l'URL nel browser, l'immagine viene ovviamente visualizzata correttamente, poiché il browser invia la sessione con la richiesta. Ma quando Flying Saucer rende il pdf, non include l'immagine protetta perché non sa nulla della sessione.

Quindi, la mia domanda è; c'è un modo per includere i flussi di byte per Flying Saucer da risolvere, così come è possibile aggiungere font risolvibili? Ho provato qualcosa come this, ma non c'è un modo semplice per impostare l'UAC su ITextRenderer, e si è lamentato ogni volta che ho provato.

risposta

6

È possibile impostare l'UserAgentCallback in questo modo, e Flying Saucer intende utilizzare per risolvere gli URL (testato, funziona con la versione 8):

ITextRenderer renderer = new ITextRenderer(); 
renderer.getSharedContext().setUserAgentCallback(new MyUAC()); 

MyUAC dovrebbe estendere la NaiveUserAgent, e l'override del metodo resolveAndOpenStream come l'altra pagina suggerisce.

+1

Grazie, questo ha funzionato per me, anche se ho esteso la classe ITextUserAgent anziché. – ManiSto

+0

@ManiSto Sto affrontando il problema esatto che hai dovuto affrontare. Potresti darmi qualche esempio di codice su come hai implementato MyUAC()? –

2

I overrode ITextUserAgent - dalla sorgente, sembra che sia quello che usa ITextRenderer. Devi fornire il dispositivo di output nel costruttore, che puoi ottenere dall'oggetto di rendering. Un altro trucco è che devi impostare il "contesto condiviso" esplicitamente usando il metodo setter, altrimenti otterrai un NPE durante il rendering. Ecco il codice per impostare l'oggetto:

ITextRenderer renderer = new ITextRenderer(); 
MyUserAgentCallback uac = new MyUserAgentCallback(renderer.getOutputDevice()); 
uac.setSharedContext(renderer.getSharedContext()); 
renderer.getSharedContext().setUserAgentCallback(uac); 

Inoltre, qui è l'idea di base di MyUserAgentCallback, utilizzando l'autenticazione di base:

private static class MyUserAgentCallback extends ITextUserAgent 
{ 
    public MyUserAgentCallback(ITextOutputDevice outputDevice) 
    { 
     super(outputDevice); 
    } 

    @Override 
    protected InputStream resolveAndOpenStream(String uri) 
    { 
     if (_isProtectedResource(uri)) 
     { 
      java.io.InputStream is = null; 
      uri = resolveURI(uri); 
      try { 
       URL url = new URL(uri); 
       String encoding = new BASE64Encoder().encode ("username:password".getBytes()); 
       URLConnection uc = url.openConnection(); 
       uc.setRequestProperty ("Authorization", "Basic " + encoding); 
       is = uc.getInputStream(); 
       Log.debug("got input stream"); 
      } 
      catch (java.net.MalformedURLException e) { 
       Log.error("bad URL given: " + uri, e); 
      } 
      catch (java.io.FileNotFoundException e) { 
       Log.error("item at URI " + uri + " not found"); 
      } 
      catch (java.io.IOException e) { 
       Log.error("IO problem for " + uri, e); 
      } 
      return is; 
     } 
     else 
     { 
      return super.resolveAndOpenStream(uri); 
     } 
    } 

    private boolean _isProtectedResource(String uri) 
    { 
     // does this require authentication? 
    } 
}