2016-08-19 2 views
0

ich den Code gezogen von How to redact a large rectangle of a PDF by iTextSharp?iTextSharp 5.5.9 Redaction - Objekt Referenz nicht gefunden

Und generiert:

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(); 

Also nahm ich aus dem verlinkten Artikel, die ich verwenden sollte Input-Dateien unterscheiden, die ich war tun.

Aber am cleaner.CleanUp() Ich erhalte einen Objektverweis wurde nicht gefunden:

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() 

Ich kann nicht sehen, warum. Das Rechteck habe ich nicht verändert. Ich bin mir nicht sicher, ob da tatsächlich etwas an diesem Ort sein muss. Ich hatte Code, der zuerst eine Anmerkung hinzufügen würde, dann versuchte ich es anzuwenden. Aber es würde auch den gleichen Objektreferenzfehler erhalten.

Im obigen Code .... muss ich zuerst eine Redaktionsanmerkung erstellen, bevor ich mich bewerbe, oder soll dieser Code das Feld auswählen, das ich redigieren und alles in einem Durchgang anwenden möchte.

Das Rechteck ich will (es ist ein Adressblock), ist eigentlich: iTextSharp.text.Rectangle (45, 650, 200, 750);

+0

Bitte teilen Sie ein Beispiel-PDF, um das Problem zu reproduzieren. 'PdfCleanUpContentOperator.Invoke' ist eine zu große Methode, um zu erraten, wo ein Objekt unerwartet null ist. – mkl

+0

Ich musste das PDF-Dokument durchgehen und desensibilisieren. Aber hier ist ein Beispiel. https://www.dropbox.com/s/9h4cuyqvmv9rso6/Document.pdf?dl=0 Auch habe ich versucht, den Code auf die folgende Veränderung: 'iTextSharp.xtra.iTextSharp.text.pdf.pdfcleanup.PdfCleanUpProcessor Reiniger = new iTextSharp.xtra.iTextSharp.text.pdf.pcleanup.PdfCleanUpProcessor (stamper); ' (entfernt die Aufräumorte) Dies scheint eine Objektreferenz zu bekommen, die nicht auf contructor gefunden wird .... Ich frage mich, ob das ungültig ist. ..und dass die Aufräumorte vorhanden sein müssen? – dcole

+0

Ich habe versucht, das Problem zu reproduzieren, indem ich Ihren Code verwendete und die Rechteckkoordinaten in '45, 650, 200, 750' änderte, wie durch Ihre Frage und die Dateipfade auf meinem System angezeigt. Das Anwenden auf die Beispieldatei funktionierte leider nicht richtig. Entweder gibt es etwas Besonderes an Ihrem Setup, das Sie noch nicht erwähnt haben, oder Sie haben ein Problem in Ihrer ursprünglichen PDF-Datei repariert, als Sie es * desensibilisiert haben. – mkl

Antwort

0

der ursprünglichen Beobachtung des OP Bezüglich der Objektverweis nicht tritt

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) 

während der Bereinigungs gefunden Prozessor den Inhalt Strom einer Form XObject analysiert: Einige Befehl in der Content-Stream ungültig zu sein scheint (die meisten wahrscheinlich sind die Befehlsparameter ungültig), dh die PDF ist sehr wahrscheinlich einfach gebrochen, um damit zu beginnen.

Dieses Verhalten kann nicht mit der desensibilisierten Version des Dokuments des OP reproduziert werden. Insbesondere enthält diese desensibilisierte Version nur ein Formular xobject auf jeder Seite, das den Redaktionsbereich nicht schneidet. Wenn Sie den Redaktionsbereich erweitern, um das Formular xobject teilweise zu schneiden, erhält man eine Ausnahme. Aber es ist ein anderer, der deutlich anzeigt, dass System.Drawing.Graphics.FromImage nicht mit dem Format des Bitmap-Bildes umgehen kann, das im Formular xobject angezeigt wird.

Daher wurde der ungültige xobject-Inhalt der Form im Desensibilisierungsprozess entfernt. Um den Bereinigungscode gegen das vorliegende Problem zu härten, wird daher das Originaldokument benötigt.


In einem Kommentar der OP deutete er auch versucht, den Bereinigungsprozess in einer anderen Weise zu nennen, das heißt durch Anmerkungen an das PDF-Schwärzung Hinzufügen und dann ohne PdfCleanUpLocation den Bereinigungsprozess aufrufen. Er fügt hinzu, die Redaktion Anmerkungen wie folgt aus:

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 

Cleanup läuft jetzt auch in ein Objektverweis wurde nicht gefunden Situation, aber diesmal

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() 

Die Ursache ist in diesem Fall ein Fehler in der Bereinigungs Code. Redaktionsanmerkungen, die z.B. Adobe Reader enthält normalerweise einen zusätzlichen Parameter QuadPoints, der eine Anzahl von Vierecken enthält, die den Bereich innerhalb des Anmerkungsrechtecks ​​angeben, um tatsächlich zu reduzieren; Wenn dieser Parameter nicht vorhanden ist, muss das gesamte Rechteck redigiert werden.

iTextSharp in diesem Zusammenhang hat diesen Code:

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

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

Leider, wenn die Anmerkung keine QuadPoints hat, annotDict.GetAsArray kehrt null und die Auswertung von quadPoints.Size mit einer Ausnahme fehlschlägt. Es sollte

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

stattdessen sein.

Die OP kann durch Zugabe von QuadPoints Eintrag mit einem leeren Feld zu seiner Redaktion dieses Problem umgehen:

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

Vorsicht: Dies ist lediglich eine Abhilfe für dieses iTextSharp Problem, sollte es nicht getan werden wenn das PDF mit den Anmerkungen für andere Zwecke verwendet wird. Streng genommen bedeutet ein leerer QuadPoints Eintrag, dass nichts zu redizieren ist.


Als beiseite, gibt es ein Problem in dem Code des OP: Wenn Datei erstellen Streams für den PdfStamper zu schreiben, die er verwendet FileMode.OpenOrCreate:

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

oder

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

Wenn es bereits eine Datei mit diesem Namen gibt, die sich als länger als die neue PDF erweist, wird das Ergebnis die Größe der alten Datei haben, wobei sich der alte Inhalt noch in der zusätzlichen Spac befindet e. I.e. Die neue Datei hat im Grunde einen Papierkorbinhalt, der eine ungültige PDF erzeugt, die z.B. Adobe Reader bietet zu reparieren.

Im Allgemeinen sollte man stattdessen FileMode.Create verwenden. Von seiner Dokumentation:

FileMode.Create entspricht beantragt, dass, wenn die Datei, System.IO.FileMode.CreateNew existiert nicht verwenden; Andernfalls verwenden Sie System.IO.FileMode.Truncate.

+0

Hallo Danke für diese detaillierte Analyse. Ich werde ein paar andere PDF-Dateien versuchen, die ich hier habe ... aber leider kann ich die originalen nicht teilen, da sie von einer kommerziellen Anwendung stammen. In Bezug auf die PDF-Probleme, ich verwende ITEXT in anderen Aspekten (Zusammenführung und die Anwendung eines Wasserzeichens), aber Sie sagen, dass für die Zwecke der Redaktion sind sie ungültig? – dcole

+0

* "aber sagst du, dass sie für die Redaktion ungültig sind?" * - Nein, ich sage nur, dass es einen Fehler gibt. Es gibt kaum eine Software ohne Bugs. Darüber hinaus führt der Fehler zu einer Ausnahme, so dass keine falsche Vorstellung von einer erfolgreichen Ausführung entsteht. Daher ist es nicht die schlimmste Art von Bug. – mkl

+0

Btw ich fügte hinzu: 'annotation.Put (PdfName.SUBTYPE, neue PdfName (" Redact ")); annotation.Put (PdfName.QUADPOINTS, neues PdfArray()); // <<<<<<<< stamper.AddAnnotation (Anmerkung, Seite); ' wie erwähnt, und diese zweite Methode funktioniert. Ich habe hier eine Reihe von PDFs gefunden, die redactierbar waren. Es gibt ein bestimmtes Szenario, das nicht zu funktionieren scheint. – dcole