2011-01-24 9 views
6

Używam Flying Saucer do utworzenia pliku pdf z xhtml, hostowanego na serwerze Tomcat. Większość zdjęć zawartych w pliku pdf jest publicznie dostępna (logo i tak dalej), ale niektóre z nich są chronione za loginem (to znaczy są przesyłane strumieniowo przez serwlet, jeśli użytkownik jest zalogowany).Rozwiązywanie chronionych zasobów za pomocą latającego talerza (ITextRenderer)

Po wklejeniu adresu URL w przeglądarce obraz jest oczywiście wyświetlany prawidłowo, ponieważ przeglądarka wysyła sesję z żądaniem. Ale kiedy Flying Saucer renderuje plik PDF, nie zawiera chronionego obrazu, ponieważ nie wie nic o sesji.

Moje pytanie brzmi; czy istnieje sposób na dołączenie strumieni bajtów do Latającego Spodka do rozwiązania, tak jak można dodawać rozpoznawalne czcionki? Próbowałem coś takiego jak this, ale nie ma prostego sposobu na ustawienie UAC na ITextRenderer i za każdym razem uskarżałem się.

Odpowiedz

6

Można ustawić UserAgentCallback ten sposób, a Latający spodek użyje go rozwiązać adresy URL (testowane, współpracuje z wersji 8):

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

MyUAC powinien przedłużyć NaiveUserAgent i zastąpić metodę resolveAndOpenStream jako druga strona sugeruje.

+1

Dzięki, to pracował dla mnie, chociaż ja rozszerzyć klasę ITextUserAgent zamiast. – ManiSto

+0

@ManiSto Mam do czynienia z dokładnym problemem, z którym się spotkałeś. Czy możesz podać mi przykładowy kod na temat tego, w jaki sposób zaimplementowano MyUAC()? –

2

I overrode ITextUserAgent również - ze źródła, wygląda na to, co używa ITextRenderer. Musisz dostarczyć urządzenie wyjściowe do konstruktora, które możesz uzyskać z obiektu renderującego. Innym problemem było to, że musisz jawnie ustawić "wspólny kontekst" za pomocą metody ustawiającej - w przeciwnym razie otrzymasz NPE podczas renderowania. Oto kod, aby ustawić obiekt:

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

Również tutaj jest podstawowa idea MyUserAgentCallback, stosując podstawowe uwierzytelnianie:

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? 
    } 
} 
Powiązane problemy