2009-02-17 41 views
13

Tôi nhận được Tệp qua Tải lên HTTP và cần đảm bảo tệp PDF của tệp đó. Ngôn ngữ lập trình là Python, nhưng điều này không quan trọng.Kiểm tra xem Tệp PDF có hợp lệ không (Python)

Tôi nghĩ đến các giải pháp sau:

  1. Kiểm tra xem các byte đầu tiên của chuỗi là "% PDF". Đây không phải là một kiểm tra tốt nhưng ngăn việc sử dụng tải lên các tệp khác một cách vô tình.

  2. Dùng thử libmagic (lệnh "tệp" trên bash sử dụng nó). Điều này thực hiện kiểm tra chính xác giống như 1.

  3. Đọc thư và thử đọc số trang. Nếu lib có thể đọc được một trang, nó phải là một pdf hợp lệ. Vấn đề: Tôi không biết một lib cho python mà có thể làm được điều này

Vì vậy, bất cứ ai có bất kỳ giải pháp cho một lib hoặc lừa khác?

Cảm ơn

Trả lời

10

Hai phổ biến nhất là sử dụng các thư viện PDF cho Python là:

Cả hai đều là trăn tinh khiết như vậy nên dễ dàng cài đặt cũng được cross-nền tảng.

Với pyPdf nó có lẽ sẽ đơn giản như thực hiện:

from pyPdf import PdfFileReader 
doc = PdfFileReader(file("upload.pdf", "rb")) 

này nên là đủ, nhưng doc bây giờ sẽ có documentInfo()numPages() phương pháp nếu bạn muốn làm kiểm tra thêm. Khi Carl trả lời, pdftotext cũng là một giải pháp tốt, và có lẽ sẽ nhanh hơn trên các tài liệu rất lớn (đặc biệt là những tài liệu có nhiều tài liệu tham khảo chéo). Tuy nhiên, nó có thể chậm hơn một chút đối với PDF nhỏ do hệ thống chi phí của việc giả mạo một quy trình mới, v.v.

2

Nếu bạn đang ở trên một Linux hoặc hộp OS X, bạn có thể sử dụng Pdftotext (một phần của xpdf, tìm thấy here). Nếu bạn chuyển một non-PDF sang pdftotext, nó chắc chắn sẽ sủa vào bạn, và bạn có thể sử dụng lệnh commands.getstatusoutput để lấy kết quả đầu ra và phân tích nó cho các cảnh báo này.

Nếu bạn đang tìm kiếm giải pháp độc lập nền tảng, bạn có thể sử dụng pyPdf.

Chỉnh sửa: Nó không thanh lịch, nhưng có vẻ như PdfFileReader của pyPdf sẽ ném IOError (22) nếu bạn cố tải một tệp không phải PDF.

10

Trong một dự án nếu tôi cần kiểm tra loại mime của một số tệp được tải lên. Tôi chỉ cần sử dụng lệnh tệp như sau:

from subprocess import Popen, PIPE 
filetype = Popen("/usr/bin/file -b --mime -", shell=True, stdout=PIPE, stdin=PIPE).communicate(file.read(1024))[0].strip() 

Tất nhiên, bạn có thể muốn chuyển lệnh thực tế vào một số tệp cấu hình cũng như tùy chọn dòng lệnh khác nhau giữa các hệ điều hành (ví dụ: mac).

Nếu bạn chỉ cần biết đó là PDF hay không và không cần xử lý nó, tôi nghĩ rằng lệnh tệp là giải pháp nhanh hơn lib. Làm điều đó bằng tay là tất nhiên cũng có thể nhưng lệnh tập tin cung cấp cho bạn có thể linh hoạt hơn nếu bạn muốn kiểm tra các loại khác nhau.

+0

+1 cho đơn giản. Nếu bạn chỉ muốn được khá chắc chắn những gì bạn đã có ít nhất là cố gắng để được một PDF này là cả một đơn giản và nhanh chóng. – technicalbloke

0

Bằng hợp lệ bạn có nghĩa là nó có thể được hiển thị bằng trình xem PDF hoặc văn bản có thể được trích xuất không? Chúng là hai thứ rất khác nhau.

Nếu bạn chỉ muốn kiểm tra xem nó thực sự là một tệp PDF đã được tải lên thì giải pháp pyPDF, hoặc một cái gì đó tương tự, sẽ hoạt động.

Nếu, tuy nhiên, bạn muốn kiểm tra xem văn bản có thể được trích xuất không thì bạn đã tìm thấy cả một thế giới đau đớn! Sử dụng pdftotext sẽ là một giải pháp đơn giản có thể hoạt động trong phần lớn các trường hợp nhưng nó không có nghĩa là thành công 100%. Chúng tôi đã tìm thấy nhiều ví dụ về các tệp PDF mà pdftotext không thể trích xuất từ ​​nhưng các thư viện Java như iText và PDFBox có thể.

8

Kể từ rõ ràng không phải PyPdf cũng không ReportLab có sẵn nữa, các giải pháp hiện tại tôi thấy (tính đến 2015) là sử dụng PyPDF2 và bắt ngoại lệ (và có thể phân tích 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 
Các vấn đề liên quan