本文介绍了在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.5the 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 nextXMLWorker 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]:

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

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]

[2]

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

09-15 01:24