4

ドキュメントに画像をシールとして挿入する iTextSharp を使用して PDF を読み取る Win32 アプリケーションがあります。

1 年以上処理しているファイルの 99% で問題なく動作しますが、最近では読み取れないファイルもあります。以下のコードを実行すると:

string inputfile = "C:\test.pdf";
PdfReader reader = new PdfReader(inputfile);

それは例外を与えます:

System.NullReferenceException occurred
  Message="Object reference not set to an instance of an object."
  Source="itextsharp"
  StackTrace:
       em iTextSharp.text.pdf.PdfReader.ReadPages()
       em iTextSharp.text.pdf.PdfReader.ReadPdf()
       em iTextSharp.text.pdf.PdfReader..ctor(String filename, Byte[] ownerPassword)
       em iTextSharp.text.pdf.PdfReader..ctor(String filename)
       em MyApp.insertSeal() na C:\MyApp\Stamper.cs:linha 659

これらの例外をスローする pdf ファイルは通常、adobe pdf で読み取ることができます。これらのファイルの 1 つを Acrobat で開いて保存すると、この保存されたファイルをアプリケーションで読み取ることができます。

ファイルは破損していますが、Adobe Reader で開くことができますか?

ファイルの 2 つのサンプルを共有しています。

動作しないファイル: Not-Ok-Version.pdf

そして、Acrobatで開いて保存した後、機能するファイル。ダウンロードはこちらOK-Version.pdf

4

5 に答える 5

9

readPages の (java、申し訳ありません) ソースは次のとおりです。

protected internal void ReadPages() {
  catalog = trailer.GetAsDict(PdfName.ROOT);
  rootPages = catalog.GetAsDict(PdfName.PAGES);
  pageRefs = new PageRefs(this);
}

trailer,catalog ,rootPages , andpageRefs` はすべて PdfReader のメンバー変数です。

PDF のトレーラーまたはルート/カタログ オブジェクトが単に欠落している場合、PDF は本当にひどく壊れています。外部参照テーブルが少しずれている可能性が高く、問題のオブジェクトが本来あるべき場所に正確に配置されていません (これは悪いことですが、回復可能です)。

ただし、PdfReader が最初に PDF を開くと、ファイル内のすべてのオブジェクトが解析され、適切な PdfObject 派生クラスに変換されます。

実行していないのは、外部参照テーブルによって要求されたオブジェクト番号と、ファイルから読み込まれたオブジェクト番号が実際に一致することを確認することです。可能性は低いですが、可能です。悪いソフトウェアは、PDF オブジェクトを間違った順序で書き出す可能性がありますが、外部参照テーブルのバイト オフセットは正しく維持します。外部参照テーブルのオブジェクト番号を、ファイル内の特定のバイト オフセットの番号で上書きするソフトウェアは問題ありません。

iTextは問題ありません。

PDFも見たいです。


うん。そのPDFは大丈夫です。具体的には:

ファイルの最初の 70kb 程度は、きれいな小さな PDF を定義します。その後、変更が PDF に追加されました。

それを確認します。誰かが PDF に変更を追加しようとして失敗しました。ひどく。どれほどひどいものかを理解するために、次の例を使用して、PDF の内部構文のいくつかを説明しましょう。

%%PDF1.6
1 0 obj
<</Type/SomeObject ...>>
endobj
2 0 obj
<</Type/SomeOtherObj /Ref 1 0 R>>
endobj
3 0 obj
...
endobj
<etc>
xref
0 10
0000000000 65535 f
0000000010 00001 n
0000000049 00002 n
0000000098 00003 n
...
trailer
<</Root 4 0 R /Size 10>>
startxref 124
%%EOF

したがって、ヘッダー/バージョン「%%PDF1.v」、オブジェクトのリスト (ここでは辞書と呼ばれます)、リスト内のすべてのオブジェクトのバイト オフセットとオブジェクト番号をリストするクロス (x) 参照テーブルがあります。ルート オブジェクトと PDF 内のオブジェクト数、および「xref」の「x」へのバイト オフセットを示すトレーラー。

既存の PDF に変更を追加できます。これを行うには、既存の %%EOF の後に新しいオブジェクトまたは変更されたオブジェクトを追加し、それらの新しいオブジェクトへのクロス リファレンス テーブルとトレーラを追加します。追加された変更のトレーラには、前の相互参照テーブルへのバイト オフセットを持つ /Prev キーが含まれている必要があります。

あなたの NOT-OKAY pdf で、誰かが PDF に変更を追加しようとしましたが、ひどく失敗しました。

元の PDF はそのまま残っています。それが Reader に表示されるものであり、PDF を保存すると得られるものです。16 進エディタで最初の %%EOF の後にあるものをすべてハッキングしたところ、ファイルは問題ありませんでした。

したがって、NOT-OKAY pdf のレイアウトは次のとおりです。

%PDF1.4.1
1 0 obj...
2 through 7
xref
0 7
<healthy xref>
trailer <</Size 8 /Root 6 0 R /Info 7 0 R>>
startxref 68308
%%EOF

ここまでは順調ですね。ここで物事が醜くなります

<binary garbage>
endstream
endobj
xref 
0 7
<horribly wrong xref>
trailer <</ID [...] /Info 1 0 R /Root 2 0 R /Size 7>>
startxref 223022
%%EOF

そのセクションで正しいのは、startxref の値だけです。

問題:

  • 2 番目のトレーラーには /Prev キーがありません。
  • 2 番目の外部参照テーブルのすべてのバイト オフセットが間違っています。
  • は「ストリーム」オブジェクトの一部ですが、そのオブジェクトの先頭が欠落しています。ストリームは次のようになります

1 0 obj
<</Type/SomeType/Length 123>>
stream
123 bytes of data
endstream
endobj

このファイルの最後は、(圧縮された)ストリームの一部で構成されています...しかし、最初に辞書がなく、使用しているフィルターとその長さを示しています(欠落しているデータは言うまでもありません) )、それでは何もできません。

誰かがこの PDF を完全に再構築しようとして、誤って元の 70kb をバージョンの先頭に上書きしたのではないかと思います。カブーム。

アドビは、追加された不適切な変更を単に無視しているように見えます。iText もこれを行うことができますが、次のこともできます

iText が PDF を開くのに失敗した場合:
1.ファイルを逆方向​​に検索して、最後から 2 番目を探します%%EOF。最後にあるものは無視して、ファイルの以前の状態が必要です。2. 最後から 2 番目以降 (存在する場合) をすべて削除し、%%EOFもう一度開いてみます。

悲しいことに、この壊れた PDF は「元の」 70kb とは完全に異なっていた可能性があり、IO エラーによってファイルの最初の部分が上書きされた可能性があります。可能性は低いですが、確実な方法はありません。

于 2011-03-22T17:38:03.517 に答える
3

それらが現在バージョン 5.0 になっていることを考えると、iTextSharp のバージョンがサポートしていない PDF バージョン仕様に書き込まれた PDF の数が増えていると思います。アップグレードを行う時期かもしれません。

于 2011-02-25T18:38:21.093 に答える
1

ソースをプルダウンして不正な PDF に対して実行すると、次の呼び出し時にReadPdf()4 番目のtryブロックで例外が発生しますReadDocObj()

"Invalid object number. at file pointer 16"

tokens.StringValuej

@Mark Storer、あなたは iText の人なので、それはあなたにとって何か意味があるかもしれません。

より高いレベルから、少なくとも私の目には、RebuildXref()が呼び出されたとき (無効な PDF が読み取られたときと思われます) は再構築されますtrailerが、catalog. 後者は、NRE が不平を言っているものです。繰り返しますが、それは単なる推測です。

于 2011-03-24T15:05:01.240 に答える
0

また、html を pdf に変換する際に、html に hr タグが含まれていないことを確認してください。

hdnEditorText.Value.Replace("\"", "'").Replace("<hr />", "").Replace("<hr/>", "")
于 2014-10-08T12:14:33.400 に答える