Fra*_*o G 3 base64 image itext
处理 IText XMLWorker 中的嵌入图像。
有没有办法在 XMLWorker 中处理嵌入式(Base64)图像?在 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;
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
你问这个问题已经快一年了,但也许这个答案无论如何都会有所帮助。
最近我遇到了类似的问题。我的目标是在生成的 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";
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在为 XMLWorker [1] 构建管道时,我将我的类的一个实例传递给上下文:
htmlPipelineContext.setImageProvider(new MyImageProvider());
Run Code Online (Sandbox Code Playgroud)
现在我们希望这应该有效。但是有一个问题!在 xmlworker 库的深处,这个 htmlPipelineContext 正在被克隆。在此操作期间,我们对 ImageProvider 的实现丢失了。这发生在 HtmlPipelineContext 的 clone() 方法中。看看274-280行(我指的是5.4.4版本):
final String rootPath = imageProvider.getImageRootPath();
newCtx.setImageProvider(new AbstractImageProvider() {
public String getImageRootPath() {
return rootPath;
}
});
Run Code Online (Sandbox Code Playgroud)
这甚至在 HtmlPipelineContext.clone() 的 javadoc [2] 中有描述:
创建此 HtmlPipelineContext 的副本,该副本仅包含初始值,不包含内部值。请注意,当前 Context 的状态不会复制到克隆中。只有像 (...) ImageProvider (new AbstractImageProvider with same 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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我只是使用它而不是 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()
| 归档时间: |
|
| 查看次数: |
5354 次 |
| 最近记录: |