使用ByteArrayOutputStream使用iText将水印添加到pdf

时间:2015-09-01 16:20:32

标签: pdf grails groovy itext bytearrayoutputstream

pdf作为byte []存储在数据库中。我想在pdf中添加一个水印,并将标记的文件存储为byte [],也在数据库中。这是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()
}

问题是pdfStamper似乎没有注意到pdfReader。在pdfReader上调用一些方法(getFileLength()和getInfo())会返回有效数据,因此pdfReader似乎没问题。与图像相同。

如果注释代码(baos.write(orig,0,orig.size())被取消注释,原始文件将保存为标记文件,但没有水印。它比原始文件大一点,但完美呈现。

上面提到的代码被注释掉了,就像在代码示例中一样,返回的byte []比原始代码小得多,而不是有效的pdf文件。

这适用于磁盘上的文件。但我在这里难倒。似乎只需要很小的东西。任何帮助将不胜感激。我已经和它斗争了好几个小时,并在网上搜索。

2 个答案:

答案 0 :(得分:0)

你忘记了一条重要的路线:

pdfStamper.close()

在此行之前插入:

return baos.toByteArray()

关闭压模时,根字典和交叉引用流等对象将写入OutputStream。没有这些对象,您就没有完整的PDF。

答案 1 :(得分:0)

关闭抛出此错误:

> 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

搜索将我带到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;
        }
    }
}