2010-09-29 20 views
5

Khi làm việc trên ứng dụng iPhone đọc nguồn cấp dữ liệu hiển thị nsdata (html và pdf) trong giao diện người dùng UIWebView. Tôi đang đánh một cái bẫy trong một số logic xác thực PDF. Tôi có một đối tượng NSData mà tôi biết có chứa một tệp có phần mở rộng .pdf. Tôi muốn hạn chế các tệp PDF không hợp lệ nhận thêm bất kỳ. Đây là lần thử đầu tiên của tôi vào mã xác thực, dường như hoạt động trong phần lớn các trường hợp:Làm cách nào để xác thực rằng NSData là một tệp PDF?

// pdfData is an NSData * 
NSData *validPDF = [[NSString stringWithString:@"%PDF"] dataUsingEncoding: NSASCIIStringEncoding]; 
if (!(pdfData && [[pdfData subdataWithRange:NSMakeRange(0, 4)] isEqualToData:validPDF])) { 
    // error 
} 

Thật không may, một tệp PDF mới đã được tải lên cách đây vài ngày. Nó hợp lệ theo nghĩa là UIWebView sẽ hiển thị nó tốt, nhưng nó không kiểm tra xác thực của tôi. Tôi đã theo dõi vấn đề về thực tế rằng đó là một loạt các byte rác ngay từ đầu, với% PDF đến giữa tập hợp các ký tự hex thứ 14 (25 hoặc% chính xác là byte thứ 54):

%PDF: 25504446 
Breaking PDF: 00010000 00ffffff ff010000 00000000 000f0100 0000b5e0 04000200 01000000 ffffffff 01000000 00000000 0f010000 0099e004 00022550 44462d31 etc... 

Thực tiễn tốt nhất để xác thực NSData là tệp PDF là gì?
Điều gì có thể sai với tệp PDF cụ thể này (nó tuyên bố rằng nó đã được mã hóa bởi PaperPort 11.0, bất kể đó là gì)?

Cảm ơn,

Mike

+0

không có gì trong ImageIO có thể giúp với điều này? – nielsbot

Trả lời

4

Câu hỏi này có vẻ khá hữu ích:

Detect if PDF file is correct (header PDF)

hoặc, nếu bạn thích phiêu lưu, here's the spec (từ trang web của Adobe here)

+0

Có, cảm ơn bạn đã liên kết. Nó hút rằng có một số fuzziness xung quanh tiêu đề. Vì vậy, tôi chỉ cần tìm kiếm 1024 byte đầu tiên của NSData cho% PDF, 4 byte tại một thời điểm, hoặc là có cách nào đó để tìm kiếm một đoạn dữ liệu cho một chuỗi ký tự? – TahoeWolverine

+0

Bạn có thể biến 1024 ký tự đầu tiên thành một NSString (sử dụng _subdatawithRange: _ của NSData để nhận được 1024 byte đầu tiên và sau đó phương thức _initWithData: encoding: _ của NSString để mã hóa nó thành đối tượng NSString) và thực hiện tìm kiếm bằng cách sử dụng rangeOfString: xem nó có ở đó không? – deanWombourne

+0

NB Hãy chắc chắn rằng bạn đã có> = 1024 byte hoặc ít nhất một trong những phương pháp đó sẽ ném một ngoại lệ;) – deanWombourne

2

Trong Swift tôi có:

var isPDF:Bool = false 
if assetData.length >= 1024 //only check if bigger 
{ 
    var pdfBytes = [UInt8]() 
    pdfBytes = [ 0x25, 0x50, 0x44, 0x46] 
    let pdfHeader = NSData(bytes: pdfBytes, length: 4) 
    let foundRange = assetData.rangeOfData(pdfHeader, options: nil, range: NSMakeRange(0, 1024)) 
    if foundRange.length > 0 
    { 
     isPDF = true 
    } 
} 
2

Có thể thử loại này ..

// Validate PDF using NSData 
    - (BOOL)isValidePDF:(NSData *)pdfData { 
     BOOL isPDF = false; 
     if (pdfData.length >= 1024) { 

      int startMetaCount = 4, endMetaCount = 5; 
      // check pdf data is the NSData with embedded %PDF & %%EOF 
      NSData *startPDFData = [NSData dataWithBytes:"%PDF" length:startMetaCount]; 
      NSData *endPDFData = [NSData dataWithBytes:"%%EOF" length:endMetaCount]; 
      // startPDFData, endPDFData data are the NSData with embedded in pdfData 
      NSRange startRange = [pdfData rangeOfData:startPDFData options:0 range:NSMakeRange(0, 1024)]; 
      NSRange endRange = [pdfData rangeOfData:endPDFData options:0 range:NSMakeRange(0, pdfData.length)]; 

      if (startRange.location != NSNotFound && startRange.length == startMetaCount && endRange.location != NSNotFound && endRange.length == endMetaCount) { 
       // This assumes the start & end PDFData doesn't have a specific range in file pdf data 
       isPDF = true; 

      } else { 
       isPDF = false; 
      } 
     } 
     return isPDF; 
    } 
+0

Bạn có thực sự cần 'malloc()' 4 byte không? Ngẫu nhiên bạn chỉ có thể sử dụng '"% PDF "' thay vì 'pdfBytes'. – trojanfoe

+0

NSData * tempData = [Dữ liệu NSDataWithBytesNoCopy: pdfBytes length: 4 freeWhenDone: YES]; Tôi đã sử dụng miễn phí khi đã đúng. Vì vậy, chúng ta cần sử dụng malloc(). –

+0

Không, bạn không có. Chỉ cần sử dụng '[NSData dataWithBytes:"% PDF "length: 4]' để thay thế. – trojanfoe

3
let fileManager = FileManager() 
    let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] 
    let rootDirectory = "\(documentsPath)/\(caption!)/" 
    let imageURL = URL(fileURLWithPath: rootDirectory).appendingPathComponent("0") 
    let ns = NSData(contentsOf: imageURL) 
    let fileExists = fileManager.fileExists(atPath: imageURL.path) 
    var isPDF:Bool = false 
    if (ns?.length)! >= 1024 //only check if bigger 
    { 
     var pdfBytes = [UInt8]() 
     pdfBytes = [ 0x25, 0x50, 0x44, 0x46] 
     let pdfHeader = NSData(bytes: pdfBytes, length: 4) 
     let a = ns?.range(of: pdfHeader as Data, options: .anchored, in: NSMakeRange(0, 1024)) 
     if (a?.length)! > 0 
     { 
      isPDF = true 


     } 
     else 
     { 
      isPDF = false 

     } 
    } 
+0

Bạn, thưa bạn, là một người tiết kiệm cuộc sống – Malik

+0

Niềm vui của tôi Mr malik –

Các vấn đề liên quan