Pierwsze rzeczy pierwsze: kiedy zostanie podpisana PDF, nie należy zmieniać żadnych bajt tym PDF, ponieważ jeśli to zrobisz, unieważnisz podpis.
Druga uwaga: znacznik kolejności bajtów to , a nie część nagłówka PDF (plik PDF zawsze zaczyna się od %PDF-1.
). W tym kontekście jest to wartość atrybutu begin
w instrukcji przetwarzania metadanych XMP. Nie znam żadnego klienta Java, który ma problem z tą sekwencją bajtów w dowolnym miejscu pliku. Jeśli mają z tym jakiś problem, jest problem z tym klientem, a nie z plikiem.
Numer Byte Order Mark wskazuje na obecność znaków UTF-8. W kontekście XMP mamy strumień wewnątrz pliku PDF, który zawiera wyraźny plik tekstowy XML, który może być wykorzystany przez oprogramowanie, które nie jest "świadome PDF". Na przykład:
2 0 obj
<</Type/Metadata/Subtype/XML/Length 3492>>stream
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.1.0-jc003">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:pdf="http://ns.adobe.com/pdf/1.3/"
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
dc:format="application/pdf"
pdf:Keywords="Metadata, iText, PDF"
pdf:Producer="iText® 5.5.4-SNAPSHOT ©2000-2014 iText Group NV (AGPL-version); modified using iText® 5.5.4-SNAPSHOT ©2000-2014 iText Group NV (AGPL-version)"
xmp:CreateDate="2014-11-07T16:36:55+01:00"
xmp:CreatorTool="My program using iText"
xmp:ModifyDate="2014-11-07T16:36:56+01:00"
xmp:MetadataDate="2014-11-07T16:36:56+01:00">
<dc:description>
<rdf:Alt>
<rdf:li xml:lang="x-default">This example shows how to add metadata</rdf:li>
</rdf:Alt>
</dc:description>
<dc:creator>
<rdf:Seq>
<rdf:li>Bruno Lowagie</rdf:li>
</rdf:Seq>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>Metadata</rdf:li>
<rdf:li>iText</rdf:li>
<rdf:li>PDF</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang="x-default">Hello World example</rdf:li>
</rdf:Alt>
</dc:title>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>
endstream
Taki zakaz PDF-aware oprogramowanie będzie szukać sekwencji W5M0MpCehiHzreSzNTczkc9d
, który jest sekwencja, która jest mało prawdopodobne, aby pojawić się przez przypadek w strumieniu danych.
Atrybut begin
wskazuje, że znaki w strumieniu używają kodowania UTF-8. Są tam, ponieważ jest to dobra praktyka dla nich, ale nie są one obowiązkowe (ISO-16684-1).
Można było pobierać metadane tak jak ty (byte[] metadata = reader.Metadata;
), usunąć bajtów i zmienić strumień z PdfStamper
przykład jak ten:
stamper.XmpMetadata = metadata;
Po zmianie metadane, można podpisać PDF.
Zauważ, że jeden aspekt twojego pytania zaskakuje mnie. Piszesz:
// metadata[0], metadata[1], metadata[2] contain the BOM
To bardzo dziwne, że pierwsze trzy bajty metadanych XMP zawierają BOM. Metadane XMP mają zaczynać się od <?xpacket
. Jeśli tak nie jest, robisz to, co trzeba, usuwając te bajty.
Zastrzeżenie: Plik PDF może zawierać metadane XMP na różnych poziomach. W tej chwili analizujesz najczęściej spotykany: metadane na poziomie dokumentu. Możesz napotkać pliki PDF z metadanymi XMP na poziomie strony, z XMP wewnątrz obrazu, itp ...
Właśnie sprawdziłem i iTextSharp nie dodaje samodzielnie LM. Oryginalne pliki PDF miały je przed podpisaniem lub w pewnym momencie dodajesz BOM. – divanov
Metadane (które są osadzone gdzieś w pliku PDF) zwykle mają LM i to jest w porządku. * Problem polega na tym, że klienci Java mają najwyraźniej problemy z tymi plikami * - które klienty Java? – mkl
@mkl: po pierwsze, InputStream odczytuje tablicę bajtów, a następnie XMLPullParse (android) zgłasza XmlPullParserException podczas analizowania xml. Używanie BOMInputStream usuwa BOM z łańcucha, tak aby XMLPullParser mógł go odczytać w każdym przypadku. Ale moim wymaganiem jest posiadanie oryginalnego pliku bez BOM. – lukasz