2012-04-10 36 views
8

Tôi biết rằng tôi có thể 'tuyến tính hóa' một tệp PDF, ví dụ như sử dụng Acrobat SDK hoặc sử dụng các công cụ thương mại. Điều này cũng được gọi là 'tối ưu hóa cho web' và nó sắp xếp lại PDF để trang 1 có thể tải nhanh nhất có thể. Các tệp PDF được phân phát theo cách này được hiển thị nhanh hơn, vì trình xem PDF không phải chờ toàn bộ tệp PDF được tải xuống.Làm cách nào để xác định mức độ (tính theo byte) của trang 1 trong tệp PDF được linearized?

Cập nhật: dựa trên câu trả lời dưới đây, bây giờ tôi nhận ra rằng một tệp PDF tuyến tính không chỉ được sắp xếp lại mà còn chứa siêu dữ liệu về cấu trúc riêng của nó, dưới dạng "từ điển tuyến tính".

Tôi có một ứng dụng mà tôi muốn tìm nạp trước một số tệp PDF (kết quả của truy vấn) với dự đoán người dùng sẽ muốn xem một trong số chúng. Sẽ thật tuyệt vời nếu khách hàng của tôi có thể tải xuống trang 1 và chỉ trang 1 cho mỗi kết quả tìm kiếm. Khi người dùng chọn một trong số họ, trang 1 có thể được hiển thị ngay lập tức và phần còn lại có thể được tải xuống dưới nền.

Tôi đang tìm một giải pháp chung có thể được sử dụng phía máy chủ (Windows hoặc Linux) để xử lý trước các tệp PDF của mình, để tôi có thể lưu trữ và phân phối trang 1 và phần còn lại một cách riêng biệt. Thực sự, tất cả những gì tôi cần biết là ở đâu trong tệp PDF là byte cuối cùng cần để hiển thị đúng trang 1. Nếu tôi có thể có số này, tất cả những thứ khác sẽ theo sau.

Tôi đã duyệt ISO specification for PDF nhưng định dạng tệp có vẻ quá phức tạp đối với tôi để chỉ phân tích cú pháp nơi trang 1 kết thúc. Mặt khác, các công cụ tuyến tính hóa các tệp PDF hầu như chắc chắn phải biết trang kết thúc ở đâu.

Tôi không quan tâm đến các biến chứng của việc phân phối PDF theo từng phần cho khách hàng; phần này đã được giải quyết kể từ khi khách hàng là một ứng dụng, không phải là một trình duyệt, và tôi có toàn quyền kiểm soát.

Tôi cũng không nghĩ rằng nó sẽ giúp tôi chia nhỏ tệp PDF bằng các công cụ như AP Split thành PDF "trang 1" và PDF hoàn chỉnh. Nếu tôi làm vậy, tôi sẽ không thể đánh lừa người xem khách hàng nghĩ rằng đó là một tệp PDF duy nhất và sẽ có sự nhấp nháy đáng chú ý khi tôi thay thế PDF "trang 1" bằng PDF đầy đủ.

Bất kỳ trợ giúp hoặc gợi ý nào được đánh giá cao.

Giải pháp (dựa trên câu trả lời của Bobrovsky dưới đây):

Một đúng tuyến tính PDF bắt đầu với một dòng tiêu đề (quy định tại mục 7.5.2 của spec PDF) như "% PDF-1.7" tiếp theo dòng chú thích của ít nhất bốn ký tự nhị phân (được định nghĩa là giá trị byte là 128 hoặc cao hơn). Ví dụ:

%PDF-1.7 
    %¤¤¤¤ 

Tiêu đề này được theo sau bởi từ điển tuyến tính hóa (được định nghĩa trong Phụ lục F trong thông số PDF). Ví dụ:

43 0 obj 
    << /Linearized 1.0 % Version 
    /L 54567 % File length 
    /H [475 598] % Primary hint stream offset and length (part 5) 
    /O 45  % Object number of first page’s page object (part 6) 
    /E 5437 % Offset of end of first page 
    /N 11  % Number of pages in document 
    /T 52786 % Offset of first entry in main cross-reference table (part 11) 
    >> 
    endobj 

Trong ví dụ này, phần cuối của trang đầu tiên là byte offset 5437. Cấu trúc dữ liệu này đủ đơn giản để phân tích bằng cách sử dụng nhiều ngôn ngữ. "43 obj" điều cho một ID cho từ điển này (43) và một số thế hệ (luôn luôn bằng không cho các tập tin tuyến tính). Từ điển chính nó được bao quanh bởi < < và >>, giữa đó là cặp giá trị khóa (các phím có dấu gạch chéo như "/ E").

Và đây là một phương pháp C# mà thấy số lượng có liên quan sử dụng một regex:

public int GetPageOneLength(byte[] data) 
{ 
    // According to ISO PDF spec: "The linearization parameter dictionary shall be entirely contained within the first 1024 bytes of the PDF file" (p. 679) 
    string preamble = new string(ASCIIEncoding.ASCII.GetChars(data, 0, 1024)); // Note that the binary section on line 2 of the header will be entirely converted to question martks ('?') 
    var match = Regex.Match(preamble, @"<<\w*/Linearized.+/E\s+(?<offset>\d+).+>>"); 
    if (!match.Success) throw new InvalidDataException("PDF does not have a proper linearization dictionary"); 
    return int.Parse(match.Groups["offset"].Value); 
} 

Note caveat Bobrovsky rằng một tập tin có thể chứa từ điển tuyến tính, tuy nhiên có thể không được linearized đúng cách (có lẽ vì một chỉnh sửa gia tăng ?). Trong trường hợp của tôi, đây không phải là vấn đề, vì tôi sẽ tuyến tính hóa tất cả các tệp PDF.

+1

Thông báo khác: Tôi đã thấy các tệp PDF có byte rác giữa tiêu đề và bắt đầu từ điển tuyến tính hóa. – Bobrovsky

Trả lời

3

Từ điển tuyến tính sẽ giúp bạn thực hiện việc này.

Từ điển cần thiết để chứa E tham số đó là

Các bù đắp Tính đến cuối trang đầu tiên (cuối phần 6 trong ví dụ F.1), liên quan đến sự khởi đầu của tập tin.

Xin lưu ý rằng không phải mọi tệp có từ điển tuyến tính thực sự được tuyến tính hóa (máy phát bị hỏng, thay đổi sau khi tuyến tính ...) Vì vậy, bạn không thể sử dụng phương pháp được mô tả nếu tệp của bạn chưa được xác minh .

Vui lòng xem F.2.2 Từ điển tham số tuyến tính hóa (Phần 2) trong PDF Tham khảo để biết thêm thông tin về từ điển tuyến tính hóa.

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