2016-08-19 63 views
0

我把代碼How to redact a large rectangle of a PDF by iTextSharp?iTextSharp的5.5.9節錄 - 對象未發現

而產生的:

iTextSharp.text.pdf.PdfReader reader; 
    reader = new iTextSharp.text.pdf.PdfReader(new System.IO.FileStream(txtPDFFile.Text, System.IO.FileMode.Open)); 
    string path = System.IO.Path.GetDirectoryName(txtPDFFile.Text); 
    System.IO.Stream fsOut = new System.IO.FileStream(System.IO.Path.Combine(path,"redacted.pdf"), System.IO.FileMode.OpenOrCreate); 
    iTextSharp.text.pdf.PdfStamper stamper = new iTextSharp.text.pdf.PdfStamper(reader, fsOut); 
List<iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpLocation> cleanUpLocations = new List<iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpLocation>(); 
     cleanUpLocations.Add(new iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpLocation(1, new iTextSharp.text.Rectangle(77f, 77f, 200f, 200f), iTextSharp.text.BaseColor.GRAY)); 
     iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpProcessor cleaner = new iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpProcessor(cleanUpLocations, stamper); 
     cleaner.CleanUp(); 
     stamper.Close(); 
     reader.Close(); 

所以我從鏈接的文章,我應該使用不同的輸入文件,這點我是花了這樣做。

但在cleaner.CleanUp()我得到找不到對象的引用:

at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpContentOperator.Invoke(PdfContentStreamProcessor pdfContentStreamProcessor, PdfLiteral oper, List`1 operands) 
    at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.InvokeOperator(PdfLiteral oper, List`1 operands) 
    at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.ProcessContent(Byte[] contentBytes, PdfDictionary resources) 
    at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.FormXObjectDoHandler.HandleXObject(PdfContentStreamProcessor processor, PdfStream stream, PdfIndirectReference refi) 
    at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.DisplayXObject(PdfName xobjectName) 
    at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.Do.Invoke(PdfContentStreamProcessor processor, PdfLiteral oper, List`1 operands) 
    at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpContentOperator.Invoke(PdfContentStreamProcessor pdfContentStreamProcessor, PdfLiteral oper, List`1 operands) 
    at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.InvokeOperator(PdfLiteral oper, List`1 operands) 
    at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.ProcessContent(Byte[] contentBytes, PdfDictionary resources) 
    at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpProcessor.CleanUpPage(Int32 pageNum, IList`1 cleanUpLocations) 
    at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpProcessor.CleanUp() 
    at Com.EDS.DocSol.PDFExtract.PDFExtractForm.btnRedaction_Click(Object sender, EventArgs e) in D:\Users\me\Code\PDFExtract\PDFExtract\PDFExtractForm.cs:line 106 
    at System.Windows.Forms.Control.OnClick(EventArgs e) 
    at System.Windows.Forms.Button.OnClick(EventArgs e) 
    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) 
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) 
    at System.Windows.Forms.Control.WndProc(Message& m) 
    at System.Windows.Forms.ButtonBase.WndProc(Message& m) 
    at System.Windows.Forms.Button.WndProc(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) 
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
    at System.Windows.Forms.Application.Run(Form mainForm) 
    at Com.EDS.DocSol.PDFExtract.Program.Main(String[] args) in D:\Users\me\Code\PDFExtract\PDFExtract\Program.cs:line 140 
    at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) 
    at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Threading.ThreadHelper.ThreadStart() 

我不明白爲什麼。矩形我沒有改變。我不確定在那個位置是否真的有事。我有一些代碼會首先添加註釋,然後我嘗試應用它。但它也會得到相同的對象引用錯誤。

在上面的代碼....我需要在申請前先創建一個新版本的註釋,或者是這個代碼選擇我要編修箱和應用它都在同一個通行證。

的Rectangle我想要(它是一個地址塊),實際上是:iTextSharp.text.Rectangle(45,650,200,750);

+0

請分享樣本PDF以重現此問題。 'PdfCleanUpContentOperator.Invoke'是一種猜測對象意外爲空的方法。 – mkl

+0

我不得不通過並使PDF文檔不敏感。但這裏是一個示例。 https://www.dropbox.com/s/9h4cuyqvmv9rso6/Document.pdf?dl=0 此外,我嘗試將代碼更改爲以下內容: 'iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpProcessor清潔程序= new iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpProcessor(stamper);' (刪除清理位置)這似乎得到一個對象引用沒有找到構造....我不知道這是無效的。 ..清理地點必須存在? – dcole

+0

我試圖重現問題,使用您的代碼並將矩形座標更改爲'45,650,200,750',如您的問題和系統上存在的文件路徑所示。將它應用到你的示例文件不幸的是工作正常。因此,對於您尚未提及的設置,有一些特殊之處,或者當您*脫敏時,您在原始PDF文件中修復了問題。 – mkl

回答

0

關於OP的原始觀察,沒有發現對象引用

at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpContentOperator.Invoke(PdfContentStreamProcessor pdfContentStreamProcessor, PdfLiteral oper, List`1 operands) 
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.InvokeOperator(PdfLiteral oper, List`1 operands) 
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.ProcessContent(Byte[] contentBytes, PdfDictionary resources) 
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.FormXObjectDoHandler.HandleXObject(PdfContentStreamProcessor processor, PdfStream stream, PdfIndirectReference refi) 
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.DisplayXObject(PdfName xobjectName) 
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.Do.Invoke(PdfContentStreamProcessor processor, PdfLiteral oper, List`1 operands) 
at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpContentOperator.Invoke(PdfContentStreamProcessor pdfContentStreamProcessor, PdfLiteral oper, List`1 operands) 
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.InvokeOperator(PdfLiteral oper, List`1 operands) 
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.ProcessContent(Byte[] contentBytes, PdfDictionary resources) 

而清理處理器解析一個表單x對象的內容流發生:所述內容流中的一些指令似乎無效(最可能指令參數是無效的),也就是說,PDF很可能只是被打斷而已。

此行爲不能與版本的OP文檔的脫敏版本一同複製。特別是,脫敏版本只在每個頁面上包含一個xobject,它不會與編輯區域相交。擴展編輯區域以部分與表單xobject相交時,會出現異常。但它是一個不同的,清楚地表明System.Drawing.Graphics.FromImage無法處理xobject表單中顯示的位圖圖像的格式。

因此,無效的形式X對象的內容似乎在脫敏過程中被刪除。因此,針對手頭的問題強化清理代碼,需要原始文檔。


在評論中表示OP他也試圖通過添加新版本註釋到PDF,然後調用清理過程不PdfCleanUpLocation調用清理過程以不同的方式,即。他補充稱,新版本的註釋是這樣的:

PdfReader reader = new PdfReader(new FileStream(txtPDFFile.Text, FileMode.Open)); 
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(txtPDFFile.Text + ".pdf", FileMode.OpenOrCreate))) 
{ 
    // Add the annotations 
    int page = 1; 
    Rectangle rect = new Rectangle(45, 650, 200, 750); 
    PdfAnnotation annotation = new PdfAnnotation(stamper.Writer, rect); 
    annotation.Put(PdfName.SUBTYPE, new PdfName("Redact")); 
    stamper.AddAnnotation(annotation, page); 
} //Using 

清理,現在也跑入沒有發現形勢對象的引用,但這次

at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpProcessor.ExtractLocationsFromRedactAnnot(Int32 page, Int32 annotIndex, PdfDictionary annotDict) 
at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpProcessor.ExtractLocationsFromRedactAnnots(Int32 page, PdfDictionary pageDict) 
at iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpProcessor.ExtractLocationsFromRedactAnnots() 

在這種情況下,原因是在清理中的錯誤碼。由例如產生的編輯註釋ADOBE READER通常包含一個額外的參數,QuadPoints,其中包含大量指定註解矩形實際纂內的區域四邊形的;如果此參數不存在,整個矩形將被編輯。

iTextSharp的在這方面有這樣的代碼:

PdfArray quadPoints = annotDict.GetAsArray(PdfName.QUADPOINTS); 

if (quadPoints.Size != 0) { 
    markedRectangles.AddRange(TranslateQuadPointsToRectangles(quadPoints)); 
} else { 
    ... add a range for the annotation rectangle ... 
} 

不幸的是,如果註解沒有QuadPointsannotDict.GetAsArray回報nullquadPoints.Size評估失敗的異常。它應該是

if (quadPoints != null && quadPoints.Size != 0) { 

改爲。

的OP可以解決此通過添加QuadPoints進入一個空數組他的節錄:

... 
annotation.Put(PdfName.SUBTYPE, new PdfName("Redact")); 
annotation.Put(PdfName.QUADPOINTS, new PdfArray()); // <<<<<<<< 
stamper.AddAnnotation(annotation, page); 
... 

當心:這只是對於該iTextSharp的問題的解決方法,它不應該做的如果帶註釋的PDF是用於其他用途的話。嚴格來說,一個空的四分點條目表示沒有任何內容需要編輯。


順便說一句,沒有在OP代碼的問題:在創建文件流的PdfStamper寫,他用FileMode.OpenOrCreate

System.IO.Stream fsOut = new System.IO.FileStream(System.IO.Path.Combine(path,"redacted.pdf"), System.IO.FileMode.OpenOrCreate); 

using (PdfStamper stamper = new PdfStamper(reader, new FileStream(txtPDFFile.Text + ".pdf", FileMode.OpenOrCreate))) 

如果已經有一個名稱更長的文件比新的PDF文件更長,那麼結果將會是舊文件的大小,舊內容仍然在額外的空間中即即新文件有效地具有懸掛的垃圾內容,這使得無效的PDF例如Adobe Reader提供修復。

一般來說,應該使用FileMode.Create來代替。從它的文檔:

FileMode.Create相當於請求,如果文件不存在,使用System.IO.FileMode.CreateNew;否則,請使用System.IO.FileMode.Truncate

+0

嗨,謝謝你的詳細分析。我會嘗試我在這裏的其他一些PDF文件...但不幸的是無法分享原來的文件,因爲它們來自商業用途應用程序。 關於有問題的PDF,我確實在其他方面使用了itext(合併和應用水印),但是您是否認爲爲了進行編輯而失效? – dcole

+0

*「但你是說爲了編輯它們是無效的嗎?」* - 不,我只是說有一個錯誤。幾乎沒有任何軟件沒有缺陷。此外,該錯誤導致一個異常,所以它不會造成成功執行的錯誤印象。因此,這不是最糟糕的一種錯誤。 – mkl

+0

btw我加了: 'annotation.Put(PdfName.SUBTYPE,new PdfName(「Redact」)); annotation.Put(PdfName.QUADPOINTS,new PdfArray()); // <<<<<<<< stamper.AddAnnotation(註解,頁面);' 如上所述,第二種方法奏效。我在這裏發現了許多可以反應的PDF文件。有一種情況似乎並不奏效。 – dcole