【问题标题】:Add watermark to pdf using iText using ByteArrayOutputStream使用 iText 使用 ByteArrayOutputStream 将水印添加到 pdf
【发布时间】:2015-09-01 16:20:32
【问题描述】:

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()
}

问题在于 pdfStamper 似乎没有注意到 pdfReader。在 pdfReader 上调用一些方法(getFileLength() 和 getInfo())返回有效数据,所以 pdfReader 似乎没问题。与图片相同。

如果注释代码(baos.write(orig, 0, orig.size()) 未注释,则原始文件保存为加盖文件,但没有水印。它比原始文件大一点,但渲染完美.

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

这适用于磁盘上的文件。但我被难住了。似乎只需要一些小东西。任何帮助将不胜感激。我已经为此奋斗了几个小时并在网上搜索。

【问题讨论】:

    标签: pdf grails groovy itext bytearrayoutputstream


    【解决方案1】:

    您忘记了重要的一行:

    pdfStamper.close()
    

    在这一行之前插入:

    return baos.toByteArray()
    

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

    【讨论】:

    • 布鲁诺,感谢您的回答。关闭不仅关闭压模,而且将所有内容写入包。关闭抛出此错误:
    • 确实:您希望将所有内容都写入baos(否则您的 PDF 文件不完整)。您收到的错误与 XMP 数据有关。您使用的是哪个版本的 iText?我已经很久没有看到这个错误了。另外:您确定原始 PDF 中的 XMP 元数据正确吗?好像Adobe的XMP解析器解析不了。
    • 嗨布鲁诺,很抱歉拖了这么久才回来。它是从网站下载的 5.5.6。即使使用 Groovy 代码,我也可以使用它,但使用的是旧版本 Grails 中提供的 Itext。
    【解决方案2】:

    关闭抛出此错误:

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

    【讨论】:

      猜你喜欢
      • 2018-03-31
      • 2018-07-12
      • 2012-11-03
      • 2015-06-04
      • 1970-01-01
      • 2014-02-17
      • 1970-01-01
      • 2017-12-19
      • 1970-01-01
      相关资源
      最近更新 更多