2013-02-13 10 views
2

Обработка встроенных изображений в IText XMLWorker.Обработка встроенных изображений в IText XMLWorker

Есть ли способ обработки встроенных (Base64) изображений в XMLWorker? В версии 5.3.5 ImageProvider Я не работает больше (исключение возникает раньше), так что я Заплатанный ImageRetrieve следующим образом, но, очевидно, это будет нарушена в следующем обновлении XMLWorker:

package com.itextpdf.tool.xml.net; 

import java.io.File; 
import java.io.IOException; 
import java.net.MalformedURLException; 

import com.itextpdf.text.BadElementException; 
import com.itextpdf.text.Image; 
import com.itextpdf.text.pdf.codec.Base64; 
import com.itextpdf.tool.xml.net.exc.NoImageException; 
import com.itextpdf.tool.xml.pipeline.html.ImageProvider; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 


/** 
* @author redlab_b 
* 
*/ 
public class ImageRetrieve { 
    final static Pattern INLINE_PATTERN = Pattern.compile("^/data:image/(png|jpg|gif);base64,(.*)"); 

    private final ImageProvider provider; 
    /** 
    * @param imageProvider the provider to use. 
    * 
    */ 
    public ImageRetrieve(final ImageProvider imageProvider) { 
     this.provider = imageProvider; 
    } 
    /** 
    * 
    */ 
    public ImageRetrieve() { 
     this.provider = null; 
    } 
    /** 
    * @param src an URI that can be used to retrieve an image 
    * @return an iText Image object 
    * @throws NoImageException if there is no image 
    * @throws IOException if an IOException occurred 
    */ 
    public com.itextpdf.text.Image retrieveImage(final String src) throws NoImageException, IOException { 
     com.itextpdf.text.Image img = null; 
     if (null != provider) { 
      img = provider.retrieve(src); 
     } 

     if (null == img) { 
      String path = null; 
      if (src.startsWith("http")) { 
       // full url available 
       path = src; 
      } else if (null != provider){ 
       String root = this.provider.getImageRootPath(); 
       if (null != root) { 
        if (root.endsWith("/") && src.startsWith("/")) { 
         root = root.substring(0, root.length() - 1); 
        } 
        path = root + src; 
       } 
      } else { 
       path = src; 
      } 
      if (null != path) { 
       try { 
        Matcher m; 
        if (path.startsWith("http")) { 
         img = com.itextpdf.text.Image.getInstance(path); 
        } else if ((m = INLINE_PATTERN.matcher(path)).matches()) { 
         // Let's handle the embedded image without saving it 
         try { 
         byte[] data = Base64.decode(m.group(2)); 
         return Image.getInstance(data); 
         } catch (Exception ex) { 
         throw new NoImageException(src, ex); 
         } 
        } else { 
         img = com.itextpdf.text.Image.getInstance(new File(path).toURI().toURL()); 
        } 
        if (null != provider && null != img) { 
         provider.store(src, img); 
        } 
       } catch (BadElementException e) { 
        throw new NoImageException(src, e); 
       } catch (MalformedURLException e) { 
        throw new NoImageException(src, e); 
       } 
      } else { 
       throw new NoImageException(src); 
      } 
     } 
     return img; 
    } 



} 

ответ

4

Прошло почти год с тех пор, как вы задали этот вопрос, но, возможно, этот ответ все равно поможет.

Недавно я встретил подобную проблему. Моя цель состояла в том, чтобы включить в созданный pdf образ, хранящийся в базе данных.

Для этого я расширил com.itextpdf.tool.xml.pipeline.html.AbstractImageProvider класс и перекрываться его метод retrieve() так:

public class MyImageProvider extends AbstractImageProvider { 

    @Override 
    public Image retrieve(final String src) { 
    Image img = super.retrieve(src); 
    if (img == null) { 
     try { 
     byte [] data = getMyImageSomehow(src); 
     img = Image.getInstance(data); 
     super.store(src, img); 
     } 
     catch (Exception e) { 
     //handle exceptions 
     } 
    } 
    return img; 
    } 

    @Override 
    public String getImageRootPath() { 
    return "http://sampleurl/img"; 
    } 
} 

Затем, при строительстве трубопроводов для XMLWorker [1], я передать экземпляр моего класса в контексте:

htmlPipelineContext.setImageProvider(new MyImageProvider()); 

Теперь мы ожидаем, что это сработает. Но есть улов! Где-то, глубоко внутри библиотеки xmlworker, этот htmlPipelineContext клонируется. И во время этой операции наша реализация ImageProvider get теряется. Это происходит внутри метода clone() HtmlPipelineContext. Посмотрите на линии 274-280 (я имею в виду 5.4.4 версии):

final String rootPath = imageProvider.getImageRootPath(); 
newCtx.setImageProvider(new AbstractImageProvider() { 
    public String getImageRootPath() { 
    return rootPath; 
    } 
}); 

Это даже описано в HtmlPipelineContext.clone() 's Javadoc [2]:

Создать clone этого HtmlPipelineContext, клон содержит только начальные значения, а не внутренние значения. Остерегайтесь, состояние текущего Контекста не копируется в клон. Скопированы только конфигурационные важные вещи, такие как (...) ImageProvider (новый AbstractImageProvider с тем же ImageRootPath), (...).

Разве это не смешно? Вы получаете класс, который предназначен для расширения, делая его абстрактным, но в конце получается, что этот класс служит только владельцем собственности.

Мой обходной путь для этого:

public class MySpecialImageProviderAwareHtmlPipelineContext extends HtmlPipelineContext { 

    MySpecialImageProviderAwareHtmlPipelineContext() { 
    super(null); 
    } 

    public HtmlPipelineContext clone() { 
    HtmlPipelineContext ctx = null; 
    try { 
     ctx = super.clone(); 
     ctx.setImageProvider(new MyImageProvider()); 
    } catch (Exception e) { 
     //handle exception 
    } 
    return ctx; 
    } 

} 

Тогда я просто использовать это вместо HtmlPipelineContext.


[1] http://demo.itextsupport.com/xmlworker/itextdoc/flatsite.html#itextdoc-menu-7

[2] http://api.itextpdf.com/xml/com/itextpdf/tool/xml/pipeline/html/HtmlPipelineContext.html#clone()

1

И, надеюсь, ваше решение, кажется, был принят в более поздней версии (5.5.6 по крайней мере).

Смежные вопросы