gpt4 book ai didi

itext - 签署 PDF - 内存消耗

转载 作者:行者123 更新时间:2023-12-01 09:33:27 36 4
gpt4 key购买 nike

我尝试了一些基于 iText v1 或 v2 的数字 PDF 签名实用程序,发现似乎整个 PDF 都加载到内存中(对于 60M PDF 进程可能需要多达 300-400MB 的内存)。

最近的 iText 版本可以在不将其加载到内存中的情况下对 PDF 进行签名吗?

更新

我用 itextpdf 5.5.6 测试了布鲁诺的例子

  • PdfReader 构造函数无关紧要 - 它可以是 (src) 或 (src, null, true),或者
    (src, null, false) - 结果相同。
  • 重要的是 createSignature 中的 new File(tmp)。

  • 但是内存消耗还是很大。我试图签署 100M 文件(它是带有嵌入式附件的 PDF),峰值内存约为 325M。当然,它比没有临时文件的 540M 好,但还不够好 (((.

    最多 32K 文件。内存为 65M(我猜是 JVM 和 java 代码本身)

    使用 /usr/bin/time -v java .... 测量内存

    我用 -Xmx100m 限制了 Java 内存,但它因内存不足而崩溃:

    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

    at com.itextpdf.text.pdf.PdfReader.getStreamBytesRaw(PdfReader.java:2576) at com.itextpdf.text.pdf.PdfReader.getStreamBytesRaw(PdfReader.java:2615) at com.itextpdf.text.pdf.PRStream.toPdf(PRStream.java:230) at com.itextpdf.text.pdf.PdfIndirectObject.writeTo(PdfIndirectObject.java:158) at com.itextpdf.text.pdf.PdfWriter$PdfBody.write(PdfWriter.java:420) at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:398) at com.itextpdf.text.pdf.PdfWriter.addToBody(PdfWriter.java:887) at com.itextpdf.text.pdf.PdfStamperImp.close(PdfStamperImp.java:412) at com.itextpdf.text.pdf.PdfStamperImp.close(PdfStamperImp.java:386) at com.itextpdf.text.pdf.PdfSignatureAppearance.preClose(PdfSignatureAppearance.java:1316) at com.itextpdf.text.pdf.security.MakeSignature.signDetached(MakeSignature.java:140)



    代码是:
    public static byte[] getStreamBytesRaw(final PRStream stream, final RandomAccessFileOrArray file) throws IOException {
    PdfReader reader = stream.getReader();
    byte b[];
    if (stream.getOffset() < 0)
    b = stream.getBytes();
    else {
    ----> b = new byte[stream.getLength()];
    file.readFully(b);

    我在调试器中看到流类型是 EmbeddedFile 并且长度是 100M - 所以整个嵌入式文件正在被读入内存。

    更新 - 创建大 PDF

    很难共享 100M 文件 )),但这里是创建序列:
  • 运行 dd if=/dev/urandom of=file.bin bs=1048000 count=100
  • 转至 http://blog.didierstevens.com/programs/pdf-tools/并取 http://didierstevens.com/files/software/make-pdf_V0_1_6.zip
  • 解压运行 python make-pdf-embedded.py file.bin file.pdf

  • 这个给你 )

    我应该注意到使用 很重要/dev/urandom . /dev/zero 创建只有 100K 大小的压缩 PDF。

    无论如何,如果有必要获取我的文件,我已经在服务器上创建了 50M 文件 - http://50mpdf.tk/50m.pdf

    最佳答案

    在签署 PDF 时,iText 使用相关的内存量

  • 除非使用 PdfReader,否则将整个未签名的 PDF 读入内存在部分模式下;
  • 在内存中创建签名文件,除非使用 PdfStamper配置为使用临时文件;和
  • 除非使用 PdfStamper,否则在将未签名数据复制到待签名文件时将整个单独的 PDF 对象(例如包含嵌入文件的流)读入内存在追加模式。

  • 例如。签署 OP 提供的 50 MB 样本文件需要
  • 关于 -Xmx240m如果既不使用追加模式,也不使用临时文件,也不使用部分模式;
  • 关于 -Xmx81m如果使用临时文件而不是追加模式,部分模式没有区别;
  • 关于 -Xmx7m如果使用附加模式和临时文件,部分模式没有区别。

  • 部分模式在后面的情况下没有区别的原因是即使在非部分模式中 PdfReader在初始化期间似乎没有读取流内容。由于示例文件主要由单个大流的内容组成,因此在初始化期间读取或未读取的少数对象没有区别,特别是即使在部分模式下 PdfReader在内存中读取并保留一些反射(reflect)全局文档结构的对象,例如页面树。

    你可以在这里找到我的测试例程: CreateSignature.java .我使用 iText 5.5.7-SNAPSHOT(在这种情况下应该与 5.5.6 版本没有区别)在 64 位 MS Windows Java 8 上运行它。

    因此,对于内存友好的签名,请使用@Bruno 代码的这个变体:
    // Creating the reader and the stamper
    PdfReader reader = new PdfReader(filepath, null, true);
    FileOutputStream os = new FileOutputStream(dest);
    PdfStamper stamper =
    PdfStamper.createSignature(reader, os, '\0', new File(tmp), true);
    // Creating the appearance
    PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
    appearance.setReason(reason);
    appearance.setLocation(location);
    appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
    // Creating the signature
    ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
    ExternalDigest digest = new BouncyCastleDigest();
    MakeSignature.signDetached(appearance, digest, pks, chain,
    null, null, null, 0, subfilter);

    关于itext - 签署 PDF - 内存消耗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30449348/

    36 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com