检查PDF文件是否有效(Python)

时间:2009-02-17 22:53:28

标签: python file pdf

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

我想到了以下解决方案:

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

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

  3. 使用lib并尝试从文件中读取页数。 如果lib能够读取页面数,则它应该是有效的pdf。问题:我不知道python的lib可以做到这一点

  4. 所以有人为lib或其他技巧获得了任何解决方案吗?

    谢谢

7 个答案:

答案 0 :(得分:13)

由于PyPdfReportLab显然不再可用,我找到的当前解决方案(截至2015年)是使用PyPDF2并捕获异常(并可能分析getDocumentInfo() })

import PyPDF2

with open("testfile.txt", "w") as f:
    f.write("hello world!")

try:
    PyPDF2.PdfFileReader(open("testfile.txt", "rb"))
except PyPDF2.utils.PdfReadError:
    print("invalid PDF file")
else:
    pass

答案 1 :(得分:11)

在我的项目中,我需要检查一些上传文件的mime类型。我只是使用这样的文件命令:

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命令可以提供更大的灵活性。

答案 2 :(得分:10)

Python最常用的两个PDF库是:

两者都是纯python,所以应该易于安装以及跨平台。

使用pyPdf它可能就像做:

一样简单
from pyPdf import PdfFileReader
doc = PdfFileReader(file("upload.pdf", "rb"))

这应该足够了,但如果您想进一步检查,doc现在会有documentInfo()numPages()方法。

正如Carl回答的那样,pdftotext也是一个很好的解决方案,对于非常大的文档(特别是那些有很多交叉引用的文档)可能会更快。然而,由于分支新进程的系统开销等原因,小PDF可能会慢一些。

答案 3 :(得分:2)

如果您使用的是Linux或OS X,则可以使用Pdftotext(Xpdf的一部分,找到here)。如果您将非PDF格式传递给pdftotext,它肯定会咆哮您,您可以使用commands.getstatusoutput获取输出并解析它们以获取这些警告。

如果您正在寻找与平台无关的解决方案,您可以使用pyPdf

编辑:这不是很优雅,但如果您尝试加载非PDF,看起来pyPdf的PdfFileReader会抛出IOError(22)。

答案 4 :(得分:0)

有效是指您可以通过PDF查看器显示,还是可以提取文本?它们是两个非常不同的东西。

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

但是,如果你想检查文本是否可以提取,那么你已经找到了一个痛苦的世界!使用pdftotext将是一个简单的解决方案,可以在大多数情况下工作,但它绝不是100%成功。我们已经找到了许多pdftotext无法提取的PDF文件的例子,但是像iText和PDFBox这样的Java库可以。

答案 5 :(得分:0)

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

但是,到目前为止,我发现该软件仍然有用。

祝你好运。

https://sourceforge.net/projects/corruptedpdfinder/

答案 6 :(得分:0)

这是使用pdfminersix的解决方案,可以与pip install pdfminer.six一起安装:

from pdfminer.high_level import extract_text

def is_pdf(path_to_file):
    try:
        extract_text(path_to_file)
        return True
    except:
        return False

您也可以使用filetypepip install filetype):

import filetype

def is_pdf(path_to_file):
    return filetype.guess(path_to_file).mime == 'application/pdf'

这两种解决方案都不理想。

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

我已经启动了另一个thread here,询问如何在不使用库(或使用较小的库)的情况下检查文件是否为有效的PDF。