我通过HTTP-Upload获取文件,需要确保它是一个pdf文件。编程语言是Python,但这不重要。
我想到了以下解决方案:
检查字符串的第一个字节是否为“%PDF”。 这不是一个好的检查,但可以防止使用意外上传其他文件。
尝试使用libmagic(bash上的“file”命令使用它)。 这与1的检查完全相同。
使用lib并尝试从文件中读取页数。 如果lib能够读取页面数,则它应该是有效的pdf。问题:我不知道python的lib可以做到这一点
所以有人为lib或其他技巧获得了任何解决方案吗?
谢谢
答案 0 :(得分:13)
由于PyPdf
和ReportLab
显然不再可用,我找到的当前解决方案(截至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,但对我来说效率不高,因为它会无限期地挂在某些损坏的文件上。
但是,到目前为止,我发现该软件仍然有用。
祝你好运。
答案 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
您也可以使用filetype(pip install filetype
):
import filetype
def is_pdf(path_to_file):
return filetype.guess(path_to_file).mime == 'application/pdf'
这两种解决方案都不理想。
filetype
解决方案的问题在于,它不会告诉您PDF本身是否可读取 。它会告诉您该文件是否为PDF,但它可能是损坏的PDF。pdfminer
解决方案应仅返回True
。但这是一个很大的库,对于这样一个简单的功能似乎有些过分了。我已经启动了另一个thread here,询问如何在不使用库(或使用较小的库)的情况下检查文件是否为有效的PDF。