在IText XMLWorker中处理嵌入的图像 [英] Handling embedded images in IText XMLWorker

查看:171
本文介绍了在IText XMLWorker中处理嵌入的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在IText XMLWorker中处理嵌入式图像。

Handling embedded images in IText XMLWorker.

有没有办法在XMLWorker中处理嵌入式(Base64)图像?在版本5.3.5
我使用的ImageProvider不再工作(之前引发异常),
所以我修补ImageRetrieve如下,但显然这将在下一个
XMLWorker中被破坏更新:

Is there a way to handle Embedded (Base64) images in XMLWorker? In version 5.3.5 the ImageProvider I used does not work any more (an exception is raised before), so I Patched ImageRetrieve as follows, but obviously this will be broken in next XMLWorker update:

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;
    }



}


推荐答案

这几乎是你提出这个问题的年份,但也许这个答案无论如何都会有所帮助。

It's almost year since you asked this question, but maybe this answer will help anyway.

最近我遇到了类似的问题。我的目标是在生成的pdf中包含存储在数据库中的图像。

Recently I met similar problem. My goal was to include in generated pdf an image stored in database.

为此,我扩展了 com.itextpdf.tool.xml .pipeline.html.AbstractImageProvider 类并覆盖其 retrieve()方法,如下所示:

To do this I've extended the com.itextpdf.tool.xml.pipeline.html.AbstractImageProvider class and overriden its retrieve() method like this:

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]构建管道时,我将我的类的实例传递给上下文:

Then, when building pipelines for XMLWorker [1], I pass an instance of my class to context:

htmlPipelineContext.setImageProvider(new MyImageProvider());

现在我们希望这应该有效。但有一个问题!在某个地方,在xmlworker库的深处,正在克隆这个htmlPipelineContext。在此操作过程中,我们的ImageProvider实现会丢失。这发生在HtmlPipelineContext的clone()方法中。看看第274-280行(我参考5.4.4版本):

Now we would expect that this should work. But there's a catch! Somewhere, deep inside the xmlworker library, this htmlPipelineContext is being cloned. And during this operation our implementation of ImageProvider get's lost. This is happening inside HtmlPipelineContext's clone() method. Take a look at lines 274-280 (I refer to 5.4.4 version):

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

这甚至在HtmlPipelineContext.clone()的javadoc [2]中有描述:

This is even described in HtmlPipelineContext.clone()'s javadoc [2]:


创建此HtmlPipelineContext的克隆,该克隆仅包含初始值,而不包含内部值。请注意,当前Context的状态不会复制到克隆。只复制像(...)ImageProvider(具有相同ImageRootPath的新AbstractImageProvider),(...)这样的配置重要内容。

Create a clone of this HtmlPipelineContext, the clone only contains the initial values, not the internal values. Beware, the state of the current Context is not copied to the clone. Only the configurational important stuff like the (...) ImageProvider (new AbstractImageProvider with same ImageRootPath) , (...) are copied.

不是很有趣吗?你得到的类是为了扩展而设计的,但最后却证明,这个类只是作为一个属性持有者。

Isn't it funny? You get class that is designed for extending by making it abstract, but at the end it turns out, that this class serves only as a property holder.

我的解决方法:

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。

Then I just use this instead of 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()

这篇关于在IText XMLWorker中处理嵌入的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆