使用iText和ByteArrayOutputStream向pdf添加水印

使用iText和ByteArrayOutputStream向pdf添加水印,pdf,grails,groovy,itext,bytearrayoutputstream,Pdf,Grails,Groovy,Itext,Bytearrayoutputstream,pdf以字节[]的形式存储在数据库中。我想在pdf中添加一个水印,并以字节[]的形式将盖章文件存储在数据库中。这是一个Grails应用程序,因此代码在Groovy中。这是: def stampDocument(byte[] orig) { PdfReader pdfReader = new PdfReader(orig) ByteArrayOutputStream baos = new ByteArrayOutputStream() //baos.write(orig,

pdf以字节[]的形式存储在数据库中。我想在pdf中添加一个水印,并以字节[]的形式将盖章文件存储在数据库中。这是一个Grails应用程序,因此代码在Groovy中。这是:

def stampDocument(byte[] orig) {
    PdfReader pdfReader = new PdfReader(orig)
    ByteArrayOutputStream baos = new ByteArrayOutputStream()
    //baos.write(orig, 0, orig.size())
    PdfStamper pdfStamper = new PdfStamper(pdfReader, baos)
    com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(new URL("http://localhost:8080/IDSG/assets/stamp.jpg"));
    image.setAbsolutePosition(65f, 10f);
    image.scalePercent(40f);
    int i = 1
    while(i <= pdfReader.getNumberOfPages()){
        PdfContentByte content = pdfStamper.getUnderContent(i)
        content.addImage(image)
        i++
    }
    return baos.toByteArray()
}
def stampDocument(字节[]orig){
PdfReader PdfReader=新PdfReader(原始)
ByteArrayOutputStream bas=新的ByteArrayOutputStream()
//写入(原始,0,原始大小())
PdfStamper PdfStamper=新PdfStamper(pdfReader,BAS)
com.itextpdf.text.Image Image=com.itextpdf.text.Image.getInstance(新URL(“http://localhost:8080/IDSG/assets/stamp.jpg"));
图像。设置绝对位置(65f,10f);
图像缩放率(40f);
int i=1

而(i你忘记了一条重要的线:

pdfStamper.close()
将其插入此行的正前方:

return baos.toByteArray()

关闭母版时,诸如根字典和交叉引用流之类的对象将写入
输出流
。没有这些对象,您就没有完整的PDF。

您忘记了一条重要的行:

pdfStamper.close()
将其插入此行的正前方:

return baos.toByteArray()

关闭母版时,根词典和交叉引用流等对象将写入
输出流
。没有这些对象,您就没有完整的PDF。

关闭此错误:

> Caused by AbstractMethodError:
> javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)V
> ->>  423 | createDocumentBuilderFactory in com.itextpdf.xmp.impl.XMPMetaParser
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  |     71 | <clinit>  in     '' |    167 | parseFromBuffer in com.itextpdf.xmp.XMPMetaFactory |    153 | parseFromBuffer in     '' |
> 350 | close . . in com.itextpdf.text.pdf.PdfStamperImp |    208 |
> close     in com.itextpdf.text.pdf.PdfStamper
>由AbstractMethodError引起:
>javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)V
>->>423 | com.itextpdf.xmp.impl.XMPMetaParser中的createDocumentBuilderFactory
>在com.itextpdf.xmp.XMPMetaFactory中的parseFromBuffer中的153中的parseFromBuffer中的|
>350 |关闭..在com.itextpdf.text.pdf.PdfStamperImp | 208中|
>在com.itextpdf.text.pdf.PdfStamper中关闭
搜索让我想到了Grails或Java。我使用JDK8和最新的itext jar-5.5.6。Grails有一个旧的itext.jar-2.0.8。它仍然是com.lowagie。更改导入并使用Grails提供的Bouncycastle,而不是Grails服务,而是一个真正的Java类,我终于让它工作得很好

以下是完整的工作代码:

import com.lowagie.text.Image;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.io.IOException;

public class Stamper {
    public Stamper(){
    }

    public byte[] stampDocument(byte[] orig) {
        try{
            PdfReader pdfReader = new PdfReader(orig);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfStamper pdfStamper = new PdfStamper(pdfReader, baos);
            Image image = Image.getInstance(new URL("http://localhost:8080/IDSG/assets/stamp.jpg"));
            image.setAbsolutePosition(70f, 10f);
            image.scalePercent(40f);
            for(int i=1; i<= pdfReader.getNumberOfPages(); i++){
                PdfContentByte content = pdfStamper.getUnderContent(i);
                content.addImage(image);
            }

            pdfStamper.close();

            return baos.toByteArray();
        }
        catch (IOException e) {
            e.printStackTrace();
            return null;
        }catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
导入com.lowagie.text.Image;
导入com.lowagie.text.pdf.PdfContentByte;
导入com.lowagie.text.pdf.PdfReader;
导入com.lowagie.text.pdf.PdfStamper;
导入java.io.ByteArrayOutputStream;
导入java.net.URL;
导入java.io.IOException;
公共级压模{
公共母版(){
}
公共字节[]stampDocument(字节[]源){
试一试{
PdfReader PdfReader=新PdfReader(orig);
ByteArrayOutputStream bas=新的ByteArrayOutputStream();
PdfStamper PdfStamper=新PdfStamper(pdfReader,BAS);
Image=Image.getInstance(新URL(“http://localhost:8080/IDSG/assets/stamp.jpg"));
图像。设置绝对位置(70f,10f);
图像缩放率(40f);

对于(int i=1;iClose),此错误:

> Caused by AbstractMethodError:
> javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)V
> ->>  423 | createDocumentBuilderFactory in com.itextpdf.xmp.impl.XMPMetaParser
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  |     71 | <clinit>  in     '' |    167 | parseFromBuffer in com.itextpdf.xmp.XMPMetaFactory |    153 | parseFromBuffer in     '' |
> 350 | close . . in com.itextpdf.text.pdf.PdfStamperImp |    208 |
> close     in com.itextpdf.text.pdf.PdfStamper
>由AbstractMethodError引起:
>javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)V
>->>423 | com.itextpdf.xmp.impl.XMPMetaParser中的createDocumentBuilderFactory
>在com.itextpdf.xmp.XMPMetaFactory中的parseFromBuffer中的153中的parseFromBuffer中的|
>350 |关闭..在com.itextpdf.text.pdf.PdfStamperImp | 208中|
>在com.itextpdf.text.pdf.PdfStamper中关闭
搜索让我想到了Grails或Java。我使用JDK8和最新的itext jar-5.5.6。Grails有一个旧的itext.jar-2.0.8。它仍然是com.lowagie。更改导入并使用Grails提供的Bouncycastle,而不是Grails服务,而是一个真正的Java类,我终于让它工作得很好

以下是完整的工作代码:

import com.lowagie.text.Image;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.io.IOException;

public class Stamper {
    public Stamper(){
    }

    public byte[] stampDocument(byte[] orig) {
        try{
            PdfReader pdfReader = new PdfReader(orig);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfStamper pdfStamper = new PdfStamper(pdfReader, baos);
            Image image = Image.getInstance(new URL("http://localhost:8080/IDSG/assets/stamp.jpg"));
            image.setAbsolutePosition(70f, 10f);
            image.scalePercent(40f);
            for(int i=1; i<= pdfReader.getNumberOfPages(); i++){
                PdfContentByte content = pdfStamper.getUnderContent(i);
                content.addImage(image);
            }

            pdfStamper.close();

            return baos.toByteArray();
        }
        catch (IOException e) {
            e.printStackTrace();
            return null;
        }catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
导入com.lowagie.text.Image;
导入com.lowagie.text.pdf.PdfContentByte;
导入com.lowagie.text.pdf.PdfReader;
导入com.lowagie.text.pdf.PdfStamper;
导入java.io.ByteArrayOutputStream;
导入java.net.URL;
导入java.io.IOException;
公共级压模{
公共母版(){
}
公共字节[]stampDocument(字节[]源){
试一试{
PdfReader PdfReader=新PdfReader(orig);
ByteArrayOutputStream bas=新的ByteArrayOutputStream();
PdfStamper PdfStamper=新PdfStamper(pdfReader,BAS);
Image=Image.getInstance(新URL(“http://localhost:8080/IDSG/assets/stamp.jpg"));
图像。设置绝对位置(70f,10f);
图像缩放率(40f);

对于(int i=1;iBruno,感谢您的回答。Close不仅关闭母版,还将所有内容写入BAS。Close抛出了此错误:确实:您希望所有内容都写入
BAS
(否则您的PDF文件不完整)。您得到的错误与XMP数据有关。您使用的是哪个版本的iText?我已经很长时间没有看到此错误了。另外:您确定原始PDF中的XMP元数据是正确的吗?Adobe的XMP解析器似乎无法解析它。您好Bruno,很抱歉这么久才返回。它是从网站下载的5.5.6。我即使在Groovy代码中也可以使用它,但是使用了Grails中提供的Itext,一个较旧的版本。Bruno,谢谢你的回答。Close不仅关闭母版,而且将所有内容都写入到BAS。Close抛出了这个错误:确实:你希望所有内容都写入到
BAS
(否则你有一个不完整的PDF文件)。您得到的错误与XMP数据有关。您使用的是哪个版本的iText?我已经很长时间没有看到此错误了。另外:您确定原始PDF中的XMP元数据是正确的吗?Adobe的XMP解析器似乎无法解析它。您好Bruno,很抱歉这么久才返回。它是从网站下载的5.5.6。我即使使用Groovy也能正常工作