iText - 多次检查附件是否存在/ link 附件

iText - check if attachment exists / link attachment multiple times

有没有办法在创建文档时(而不是在文档保存到磁盘之后)检查附件是否已经存在于 PDF 文档中?在将 XML 解析为 PDF 时,我遇到了多个具有相同内容(来自 XML > byte[] 的 Base64 字符串)和相同名称的附件。目前附件已添加多次,但我想检查附件(具有相同内容或名称)是否已经存在(PdfWriter API?)如果是,则只应为现有附件创建一个新注释.

注意:检查应该在创建 PDF 时进行,而不是使用 PdfReader 和现有 PDF

编辑: 感谢@Bruno Lowagie 我让它工作了:

protected HashMap<String, PdfFileSpecification> cache = new HashMap<>();
private final byte[] BUFFER = new byte[1024];

public PdfFileSpecification getPdfFileSpecification(final PdfWriter pdfWriter, final String name, final byte[] data) throws IOException {

    String hash = createMD5Hash(data);
    PdfFileSpecification pdfFileSpecification = cache.get(hash);

    if (pdfFileSpecification == null) {
        pdfFileSpecification = PdfFileSpecification.fileEmbedded(pdfWriter, null, name, data);
        cache.put(hash, pdfFileSpecification);
        return pdfFileSpecification;
    }
    System.out.println(String.format("Name: %s Hash: %s", name, hash));
    return pdfFileSpecification;
}

private String createMD5Hash(final byte[] data) {

MessageDigest messageDigest;

    try {
        messageDigest = MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException e) {
        return null;
    }

    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);

    try {
        int i;
        while ((i = byteArrayInputStream.read(BUFFER)) != -1) {
            messageDigest.update(BUFFER, 0, i);
        }
        byteArrayInputStream.close();
    } catch (IOException e) {
        return null;
    }
    byte[] mdbytes = messageDigest.digest();

    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < mdbytes.length; i++) {
        sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
    }

    return sb.toString();
}

所以每次我必须处理一个新的附件时,我都是这样做的:

PdfFileSpecification fs = getPdfFileSpecification(pdfWriter, name, data)
PdfAnnotation an = PdfAnnotation.createFileAttachment(pdfWriter, rectangle, name, fs);

请允许我使用您的代码并介绍一些伪代码来向您展示我将如何执行此操作:

protected Map<String, PdfFileSpecification> cache =
    new HashMap<String, PdfFileSpecification>();

public void cellLayout(final PdfPCell pdfPCell, final Rectangle rectangle, final PdfContentByte[] pdfContentBytes) {
    String hasheddata = createHash(attachment);
    PdfFileSpecification fs = cache.get(hasheddata);
    if (fs == null) {
        fs = PdfFileSpecification.fileEmbedded(writer, null, displayname, attachment);
        cache.put(hasheddata, fs);
    }
    PdfAnnotation an = PdfAnnotation.createFileAttachment(writer, rectangle, displayname, fs);
    writer.addAnnotation(an);
}

这段代码无法编译,因为我遗漏了一些与问题无关的部分。我只保留了解释为文件规范创建缓存的概念的内容。

我创建了 attachment 字节的散列以节省内存。您将必须使用您选择的散列算法来实现 createHash() 方法。在我创建一个将字节写入 PdfWriter 的新 FileSpecification 之前,我检查我是否不能重用已经存在的文件规范。如果存在,我会在注释中重复使用它。如果它不存在,我会创建一个新的文件规范。