2014-10-07 8 views
7

Derzeit verwende ich PyPDF 2 als Abhängigkeit.PyPDF 2 Decrypt funktioniert nicht

Ich habe einige verschlüsselte Dateien festgestellt und behandelt sie wie gewohnt (im folgenden Code):

PDF = PdfFileReader(file(pdf_filepath, 'rb')) 
    if PDF.isEncrypted: 
     PDF.decrypt("") 
     print PDF.getNumPages() 

Mein Filepath sieht so etwas wie "~/blah/FDJKL492019 21490, LFS.pdf" PDF.decrypt ("") gibt 1 zurück, was bedeutet, dass es erfolgreich war. Aber wenn es PDF.getNumpages(), print trifft, löst es noch den Fehler aus, "PyPDF2.utils.PdfReadError: Datei wurde nicht entschlüsselt".

Wie kann ich diesen Fehler beheben? Ich kann die PDF-Datei einfach per Doppelklick öffnen (Standard-öffnet mit Adobe Reader).

Antwort

5

Um meine eigene Frage zu beantworten: Wenn Sie ANY Leerzeichen in Ihrem Dateinamen haben, dann PyPDF 2 Entschlüsselungsfunktion wird letztlich fehlschlagen trotz Rückgabe eines Erfolgscodes. Versuchen Sie, bei der Benennung Ihrer PDFs auf Unterstriche zu klicken, bevor Sie sie über PyPDF2 ausführen.

Zum Beispiel

Anstatt "FDJKL492019 21490, LFS.pdf" tun so etwas wie "FDJKL492019_21490_, LFS.pdf".

+0

Gut entdeckt! Es muss eine Einschränkung von Python oder speziell dieser Bibliothek sein (das hat nichts mit dem PDF-Format zu tun). Sie können dies auf der Website erwähnen, von wo Sie es bekommen haben. – usr2564301

+0

Es scheint, dass es auch fehlschlägt, wenn Sonderzeichen "®ø" usw. verwendet werden. – rsm

6

aufgrund dieser Fehler zustande kommen kann, auf 128-Bit-AES-Verschlüsselung auf dem pdf https://github.com/mstamy2/PyPDF2/issues/53

Eine Abhilfe sehen ist, alle IsEncrypted pdfs mit "qpdf"

qpdf --password='' --decrypt input.pdf output.pdf 

Auch zu entschlüsseln, wenn Ihre PDF tut erscheint nicht passwortgeschützt, es kann immer noch ohne Passwort verschlüsselt werden. Das obige Snippet geht davon aus, dass dies der Fall ist.

0

Es hat nichts damit zu tun, ob die Datei entschlüsselt wurde oder nicht, wenn die Methode getNumPages() verwendet wird.

Wenn wir einen Blick auf den Quellcode getNumPages() nehmen:

def getNumPages(self): 
    """ 
    Calculates the number of pages in this PDF file. 

    :return: number of pages 
    :rtype: int 
    :raises PdfReadError: if file is encrypted and restrictions prevent 
     this action. 
    """ 

    # Flattened pages will not work on an Encrypted PDF; 
    # the PDF file's page count is used in this case. Otherwise, 
    # the original method (flattened page count) is used. 
    if self.isEncrypted: 
     try: 
      self._override_encryption = True 
      self.decrypt('') 
      return self.trailer["/Root"]["/Pages"]["/Count"] 
     except: 
      raise utils.PdfReadError("File has not been decrypted") 
     finally: 
      self._override_encryption = False 
    else: 
     if self.flattenedPages == None: 
      self._flatten() 
     return len(self.flattenedPages) 

wir werden feststellen, dass es die self.isEncrypted Eigenschaft ist, den Fluss zu steuern. Und wie wir alle wissen, ist die Eigenschaft isEncrypted schreibgeschützt und nicht änderbar, selbst wenn das PDF entschlüsselt wird.

So ist die einfache Möglichkeit, die Situation zu handhaben ist nur das Passwort als Schlüssel-Wort Argument hinzufügen mit leeren String als Standardwert und Ihr Passwort übergeben, wenn die getNumPages() Verfahren und andere Verfahren unter Verwendung baut darüber hinaus

1

Die folgender Code könnte dieses Problem lösen:

import os 
import PyPDF2 
from PyPDF2 import PdfFileReader 

fp = open(filename) 
pdfFile = PdfFileReader(fp) 
if pdfFile.isEncrypted: 
    try: 
     pdfFile.decrypt('') 
     print('File Decrypted (PyPDF2)') 
    except: 
     command = ("cp "+ filename + 
      " temp.pdf; qpdf --password='' --decrypt temp.pdf " + filename 
      + "; rm temp.pdf") 
     os.system(command) 
     print('File Decrypted (qpdf)') 
     fp = open(filename) 
     pdfFile = PdfFileReader(fp) 
else: 
    print('File Not Encrypted')