-1

PDFファイルからすべての添付ファイルを抽出するC#コードがいくつかあります。ドキュメント レベルまたはファイル注釈として添付されている場合でも、うまく機能します。

ただし、これらのPDFファイルにデジタル署名(およびタイムスタンプ)すると、添付ファイルのタイプが注釈(または添付ファイル)から「ウィジェット」などに変わります。私は pdf の専門家ではなく、pdf が署名されている場合に添付ファイルを抽出する方法が見つかりませんでした。

どんな助けでも大歓迎です!

[編集]

署名なしのサンプル: samplepdf_notsigned.pdf

署名付きサンプル (SetaPDF-Signer API で署名済み): samplepdf_signed.pdf

コード ブロックは次のとおりです。

/*
 * annotations
 */
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader("samplepdf_annotations.pdf");
for (int i = 1; i <= reader.NumberOfPages; i++)
{
    iTextSharp.text.pdf.PdfArray array = reader.GetPageN(i).GetAsArray(iTextSharp.text.pdf.PdfName.ANNOTS);
    if (array == null) continue;
    for (int j = 0; j < array.Size; j++)
    {
        iTextSharp.text.pdf.PdfDictionary annot = array.GetAsDict(j);
        if (iTextSharp.text.pdf.PdfName.FILEATTACHMENT.Equals(annot.GetAsName(iTextSharp.text.pdf.PdfName.SUBTYPE)))
        {
            iTextSharp.text.pdf.PdfDictionary fs = annot.GetAsDict(iTextSharp.text.pdf.PdfName.FS);
            iTextSharp.text.pdf.PdfDictionary refs = fs.GetAsDict(iTextSharp.text.pdf.PdfName.EF);
            foreach (iTextSharp.text.pdf.PdfName name in refs.Keys)
            {
                // I CAN GET THE ATTACHMENT HERE
                string filename = fs.GetAsString(name).ToString();
                byte[] binary = iTextSharp.text.pdf.PdfReader.GetStreamBytes((iTextSharp.text.pdf.PRStream)refs.GetAsStream(name));
            }
        }
        else
        {
            iTextSharp.text.pdf.PdfDictionary fs = annot.GetAsDict(iTextSharp.text.pdf.PdfName.FS);
            iTextSharp.text.pdf.PdfDictionary refs = fs.GetAsDict(iTextSharp.text.pdf.PdfName.EF);
            foreach (iTextSharp.text.pdf.PdfName name in refs.Keys)
            {
                // I CAN GET THE ATTACHMENT HERE
                string filename = fs.GetAsString(name).ToString();
                byte[] binary = iTextSharp.text.pdf.PdfReader.GetStreamBytes((iTextSharp.text.pdf.PRStream)refs.GetAsStream(name));
            }
        }
    }
} 

/*
 * embedded level
 */
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader("samplepdf_embedded.pdf");
iTextSharp.text.pdf.PdfDictionary root = reader.Catalog;
iTextSharp.text.pdf.PdfDictionary documentnames = root.GetAsDict(iTextSharp.text.pdf.PdfName.NAMES);
iTextSharp.text.pdf.PdfDictionary embeddedfiles = documentnames.GetAsDict(iTextSharp.text.pdf.PdfName.EMBEDDEDFILES);
iTextSharp.text.pdf.PdfArray filespecs = embeddedfiles.GetAsArray(iTextSharp.text.pdf.PdfName.NAMES);
for (int i = 0; i < filespecs.Size; ) {
    filespecs.GetAsString(i++);
    iTextSharp.text.pdf.PdfDictionary filespec = filespecs.GetAsDict(i++);
    iTextSharp.text.pdf.PdfDictionary refs = filespec.GetAsDict(iTextSharp.text.pdf.PdfName.EF);
    foreach (iTextSharp.text.pdf.PdfName key in refs.Keys)
    {
        iTextSharp.text.pdf.PRStream stream = (iTextSharp.text.pdf.PRStream)iTextSharp.text.pdf.PdfReader.GetPdfObject(refs.GetAsIndirectObject(key));
        // I CAN GET THE ATTACHMENT HERE
        string filename = filespec.GetAsString(key).ToString();
        byte[] binary = iTextSharp.text.pdf.PdfReader.GetStreamBytes(stream);
    }
}
4

1 に答える 1

0

問題は、添付ファイルの注釈を見つけようとするトップ コード ブロックにあると思います。その内側のループ (すべての注釈を検査する)​​ には、次の構造があります。

if (iTextSharp.text.pdf.PdfName.FILEATTACHMENT.Equals(annot.GetAsName(iTextSharp.text.pdf.PdfName.SUBTYPE)))
{
    [...block 1...]
}
else
{
    [...block 2...]
}

ここで、ブロック 1 と 2 は同一です。つまり、添付ファイルである注釈とそうでない注釈の両方に対して、いずれの場合でもそこでコードを実行します。

PDF 内の唯一の注釈が添付ファイルである限り、それは問題ではありませんが、別の注釈が 1 つあるとすぐに、そのブロック 2 のコード

iTextSharp.text.pdf.PdfDictionary fs = annot.GetAsDict(iTextSharp.text.pdf.PdfName.FS);
iTextSharp.text.pdf.PdfDictionary refs = fs.GetAsDict(iTextSharp.text.pdf.PdfName.EF);
foreach (iTextSharp.text.pdf.PdfName name in refs.Keys)
{
    // I CAN GET THE ATTACHMENT HERE
    string filename = fs.GetAsString(name).ToString();
    byte[] binary = iTextSharp.text.pdf.PdfReader.GetStreamBytes((iTextSharp.text.pdf.PRStream)refs.GetAsStream(name));
}

他のほとんどの注釈タイプには/EFエントリがないため、顔に爆発する可能性が高く、そうrefsnullありrefs.Keys、例外が発生します。

残念なことに、統合された PDF 署名はフォーム フィールドであり、(見えなくても) 注釈としてページに添付できます。したがって、PDF に署名すると、ブロック 2 のトラップが発生します。

とにかく、なぜブロック 2 で添付ファイルを抽出しようとするのかという疑問が生じます。PDF 仕様によると、添付ファイルの注釈には、if検索対象のタイプ情報が含まれている必要があります。したがって、仕様に準拠した PDF では、コードがファイル添付注釈のブロック 2 に入ることはありません。したがって、そのブロック 2 を簡単に削除できます。

于 2013-10-02T14:28:14.333 に答える