2012-04-10 12 views
8

Wiem, że mogę "linearyzować" plik PDF, na przykład za pomocą programu Acrobat SDK lub przy użyciu narzędzi komercyjnych. Jest to również nazywane "zoptymalizowany pod kątem sieci" i zmienia kolejność pliku PDF, aby strona 1 mogła się załadować tak szybko, jak to możliwe. Pliki PDF wyświetlane w ten sposób są wyświetlane szybciej, ponieważ przeglądarka plików PDF nie musi czekać na pobranie całego pliku PDF.Jak określić rozmiar (w bajtach) strony 1 w zlinearyzowanym pliku PDF?

Aktualizacja: na podstawie odpowiedzi poniżej, ja sobie teraz sprawę, że linearized PDF nie jest tak uporządkowane, ale także zawiera metadane o własnej konstrukcji, w postaci „słownika linearyzacji”.

Mam aplikacji, gdzie chcę wstępne pobieranie kilku plików PDF (wyniki zapytania), w oczekiwaniu, że użytkownik będzie chciał zobaczyć jeden z nich. Byłoby wspaniale, gdyby mój klient mógł pobrać stronę 1 i tylko stronę 1 dla każdego z wyników wyszukiwania. Gdy użytkownik wybierze jedną z nich, strona 1 może być wyświetlona natychmiast, a pozostałą część można pobrać w tle.

Szukam ogólnego rozwiązania, które może być używane po stronie serwera (Windows lub Linux) do wstępnego przetwarzania moich plików PDF, aby można było przechowywać i udostępniać stronę 1, a resztę oddzielnie. Naprawdę, wszystko, co muszę wiedzieć, to gdzie w pliku PDF jest ostatni bajt potrzebny do poprawnego wyświetlenia strony 1. Jeśli mogę mieć ten numer, wszystko inne następuje.

Przeglądałem ISO specification for PDF, ale format pliku wydaje mi się zbyt skomplikowany, aby po prostu przeanalizować, gdzie kończy się strona 1. Z drugiej strony narzędzia, które linearyzują pliki PDF, prawie na pewno wiedzą, gdzie kończy się strona 1.

Nie jestem zainteresowany powikłań obsługujących pliki PDF w kawałkach do klientów; ta część jest już rozwiązana, ponieważ klient jest aplikacją, a nie przeglądarką i mam pełną kontrolę.

Nie sądzę, że pomoże mi podzielić PDF za pomocą narzędzi takich jak AP Split na plik PDF "strona 1" i pełny plik PDF. Jeśli to zrobię, nie będę w stanie oszukać przeglądarki klienta, myśląc, że jest to pojedynczy plik PDF, i zauważalne będzie migotanie, gdy zastępuję plik PDF "strona 1" pełnym plikiem PDF.

Każda pomoc lub wskazówki są mile widziane.

Rozwiązanie (w oparciu o odpowiedzi Bobrovsky za poniżej):

Prawidłowo linearized PDF rozpoczyna się od wiersza nagłówka (określonej w rozdziale 7.5.2 specyfikacji PDF), takie jak "% PDF-1.7", a następnie wiersz komentarza zawierający co najmniej cztery znaki binarne (zdefiniowane jako wartości bajtów równe 128 lub większe). Np

%PDF-1.7 
    %¤¤¤¤ 

Nagłówek następuje bezpośrednio przez słownik linearyzacji (określone w dodatku F w specyfikacji PDF). Przykład:

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 

W tym przykładzie, koniec pierwszej strony jest offset bajtowy 5437. Ta struktura danych jest na tyle prosty, aby analizować przy użyciu prawie każdego języka. Funkcja "43 0 obj" podaje identyfikator tego słownika (43) i numer generacyjny (zawsze zero dla zlinearyzowanych plików). Sam słownik jest otoczony przez < < i >>, pomiędzy którymi są pary wartości kluczy (klawisze mają ukośniki jak "/ E").

A oto metoda C#, który znajdzie odpowiedni numer przy użyciu 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); 
} 

Uwaga zastrzeżenie Bobrovsky, że plik może zawierać słownika linearyzacji, ale może nie być prawidłowo linearyzacji (być może z powodu bieżących edycji ?). W moim przypadku nie stanowi to problemu, ponieważ samodzielnie linearyzuję wszystkie pliki PDF.

+1

Kolejne zastrzeżenie: Widziałem pliki PDF z bajtami śmieci między nagłówkiem i początkiem słownika linearyzacji. – Bobrovsky

Odpowiedz

3

Słownik liniowy powinien ci w tym pomóc.

Słownik muszą zawierać E parametr jest

Przesunięcie końca pierwszej strony (na końcu części 6 w przykładzie F.1) w stosunku do początku pliku.

Należy pamiętać, że nie każdy plik ze słownikiem linearyzacji jest rzeczywiście linearyzacji (połamane generatory, zmiany po linearyzacji itp) Więc może nie być w stanie korzystać z opisanego podejścia, jeśli pliki nie są weryfikowane być prawidłowo linearized .

Proszę spojrzeć na F.2.2 Słownik parametrów linearyzacji (część 2) w PDF Reference, aby uzyskać więcej informacji o słowniku linearyzacji.

Powiązane problemy