使用Python检查PDF文件是否有效

使用Python检查PDF文件是否有效,python,file,pdf,Python,File,Pdf,我通过HTTP上传获得一个文件,需要确保它是pdf文件。编程语言是Python,但这不重要 我想到了以下解决方案: 检查字符串的第一个字节是否为“%PDF”。这不是一个很好的检查,但可以防止用户意外上传其他文件 尝试libmagic(bash上的“file”命令使用它)。这与(1)中的检查完全相同 获取一个lib并尝试从文件中读取页面计数。如果lib能够读取页面计数,那么它应该是有效的pdf。问题:我不知道python的lib可以做到这一点 那么有没有人能为lib或其他技巧找到解决方案?如

我通过HTTP上传获得一个文件,需要确保它是pdf文件。编程语言是Python,但这不重要

我想到了以下解决方案:

  • 检查字符串的第一个字节是否为“%PDF”。这不是一个很好的检查,但可以防止用户意外上传其他文件

  • 尝试libmagic(bash上的“file”命令使用它)。这与(1)中的检查完全相同

  • 获取一个lib并尝试从文件中读取页面计数。如果lib能够读取页面计数,那么它应该是有效的pdf。问题:我不知道python的lib可以做到这一点


  • 那么有没有人能为lib或其他技巧找到解决方案?

    如果您使用的是Linux或OS X设备,您可以使用(Xpdf的一部分,已找到)。如果您将一个非PDF文件传递给pdftotext,它肯定会对您吠叫,您可以使用commands.getstatusoutput获取输出并解析这些警告

    如果您正在寻找独立于平台的解决方案,您可能可以利用


    编辑:这并不优雅,但如果您尝试加载非PDF,pyPdf的PdfileReader似乎会抛出IOError(22)。

    在项目中,如果我需要检查某个上载文件的mime类型。我只是像这样使用file命令:

    from subprocess import Popen, PIPE
    filetype = Popen("/usr/bin/file -b --mime -", shell=True, stdout=PIPE, stdin=PIPE).communicate(file.read(1024))[0].strip()
    
    当然,您可能希望将实际命令移动到某个配置文件中,因为命令行选项在不同的操作系统(例如mac)中也有所不同


    如果您只需要知道它是否是PDF,并且不需要处理它,我认为file命令是一个比lib更快的解决方案。当然也可以手工操作,但是如果您想检查不同的类型,file命令可能会为您提供更大的灵活性。

    Python最常用的两个PDF库是:

    两者都是纯python的,因此应该易于安装,并且是跨平台的

    使用pyPdf,它可能与执行以下操作一样简单:

    from pyPdf import PdfFileReader
    doc = PdfFileReader(file("upload.pdf", "rb"))
    
    这应该足够了,但是如果您想做进一步的检查,
    doc
    现在将有
    documentInfo()
    numPages()
    方法


    正如Carl回答的那样,pdftotext也是一个很好的解决方案,在非常大的文档上(特别是有许多交叉引用的文档)可能会更快。但是,由于分叉新进程等的系统开销,小型PDF上的速度可能会稍慢。

    通过valid,您的意思是它可以由PDF查看器显示,还是可以提取文本?它们是两种截然不同的东西

    如果您只想检查它是否真的是一个已上载的PDF文件,那么pyPDF解决方案或类似的解决方案将起作用

    但是,如果您想检查文本是否可以提取,那么您已经发现了整个痛苦世界!使用pdftotext将是一个简单的解决方案,在大多数情况下都能奏效,但它绝不是100%成功的。我们发现了许多PDF示例,pdftotext无法从中提取,但Java库(如iText和PDFBox)可以提取

    更新2020 它看起来像是一个维护的项目(其他项目,包括下面的项目,似乎已经死了)

    是另一个(被我误认为死了)

    原始答案 由于显然
    PyPdf
    ReportLab
    都不再可用,因此我找到的当前解决方案(截至2015年)是使用和捕获异常(并可能进行分析)


    我遇到了同样的问题,但没有被迫使用编程语言来管理此任务。我使用pyPDF,但对我来说效率不高,因为它无限地挂在一些损坏的文件上

    然而,我发现这个软件直到现在都很有用

    祝你好运

    这是一个使用的解决方案,可与pip install pdfminer一起安装。六个:

    from pdfminer.high_level import extract_text
    
    def is_pdf(path_to_file):
        try:
            extract_text(path_to_file)
            return True
        except:
            return False
    
    您还可以使用(
    pip安装文件类型
    ):

    这两种解决方案都不理想

  • filetype
    解决方案的问题在于它不会告诉您PDF本身是否可读。它会告诉您该文件是否为PDF,但可能是损坏的PDF
  • pdfminer
    解决方案应仅在PDF实际可读时返回
    True
    。但它是一个很大的库,对于这样一个简单的函数来说似乎有些过分了

  • 我又开始询问如何在不使用库(或使用较小的库)的情况下检查文件是否为有效的PDF。

    +1为了简单起见。如果你只是想确定你得到的至少是一个PDF,这是一个既简单又快速的项目,这是一个没有维护的项目。那么它在生产中会稳定吗?@PranKumarSarkar:虽然我不再使用它了,但我查看了当前的软件包并更新了2020年的答案。ReportLab还活着,安装得很好-pip安装了ReportLab,今天在Python 3.8上获得了3.5.48版,没有问题。@SteveBarnes感谢更新。我更正了我的答案。这个使用pypdf的解决方案怎么样?它会不会比pdfminer的资源密集度低很多呢?因为它只是在创建一个阅读器?
    from pdfminer.high_level import extract_text
    
    def is_pdf(path_to_file):
        try:
            extract_text(path_to_file)
            return True
        except:
            return False
    
    import filetype
    
    def is_pdf(path_to_file):
        return filetype.guess(path_to_file).mime == 'application/pdf'