2014-10-09 18 views
7

Tôi đang sử dụng iTextSharp 5.5.1 để ký các tệp PDF bằng chữ ký tách rời (được lấy từ cơ quan bên thứ ba). Mọi thứ dường như hoạt động tốt, tệp hợp lệ và ví dụ: Adobe Reader báo cáo không có vấn đề, hiển thị các chữ ký như hợp lệ vv.Xóa Dấu xếp hàng theo thứ tự từ tệp PDF đã ký?

Vấn đề là các máy khách Java dường như có một số vấn đề với các tệp đó - tệp không thể mở hoặc phân tích cú pháp.
Các tệp có dấu thứ tự byte trong tiêu đề dường như gây ra hành vi (\ x00EF \ x00BB \ x00BF).

tôi có thể xác định được BOM như thế này:

PdfReader reader = new PdfReader(path); 
byte[] metadata = reader.Metadata; 
// metadata[0], metadata[1], metadata[2] contain the BOM 

Làm thế nào tôi có thể loại bỏ các BOM (mà không làm mất hiệu lực của chữ ký), hoặc buộc các thư viện iTextSharp không nối thêm các byte vào các tập tin?

+0

Tôi vừa kiểm tra và iTextSharp không thêm BOM. Hoặc các tệp PDF gốc đã có chúng trước khi ký hoặc bạn thêm BOM vào một thời điểm nào đó. – divanov

+0

Siêu dữ liệu (được nhúng ở đâu đó trong tệp PDF) thường có BOM và điều đó là ok. * Vấn đề là các máy khách Java dường như có một số vấn đề với các tệp đó * - mà Java Clients? – mkl

+0

@mkl: đầu tiên, InputStream đọc mảng byte, sau đó XMLPullParse (android) ném XmlPullParserException khi phân tích cú pháp xml. Sử dụng BOMInputStream loại bỏ BOM khỏi String, vì vậy XMLPullParser có thể đọc nó trong mọi trường hợp. Nhưng yêu cầu của tôi là có tệp gốc mà không có BOM. – lukasz

Trả lời

6

Trước tiên: một lần PDF được ký kết, bạn không nên thay đổi bất kỳ byte của PDF mà, bởi vì bạn làm mất hiệu lực chữ ký nếu bạn làm.

Quan sát thứ hai: dấu thứ tự byte là không một phần của tiêu đề PDF (PDF luôn bắt đầu bằng %PDF-1.). Trong ngữ cảnh này, nó là giá trị của thuộc tính begin trong hướng dẫn xử lý siêu dữ liệu XMP. Tôi không biết của bất kỳ khách hàng Java có một vấn đề với chuỗi byte đó bất cứ nơi nào trong một tập tin. Nếu họ có một vấn đề với nó, có một vấn đề với khách hàng đó, không phải với tập tin.

Byte Order Mark là chỉ báo về sự hiện diện của các ký tự UTF-8. Trong bối cảnh của XMP, chúng tôi có một luồng bên trong tệp PDF chứa tệp XML văn bản rõ ràng có thể được phần mềm tiêu thụ không phải là "nhận thức PDF". Ví dụ:

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 

phần mềm phi PDF-aware như vậy sẽ tìm kiếm các chuỗi W5M0MpCehiHzreSzNTczkc9d, mà là một chuỗi đó là khó có khả năng xuất hiện một cách tình cờ trong một dòng dữ liệu.

Thuộc tính begin có để cho biết rằng các ký tự trong luồng sử dụng mã hóa UTF-8. Họ ở đó vì thực hành tốt cho họ ở đó, nhưng họ không bắt buộc (ISO-16684-1).

Bạn có thể lấy các siêu dữ liệu theo cách bạn làm (byte[] metadata = reader.Metadata;), loại bỏ các byte, và thay đổi dòng với một trường hợp PdfStamper như thế này:

stamper.XmpMetadata = metadata; 

Sau khi bạn đã thay đổi siêu dữ liệu, bạn có thể đăng các PDF.

Lưu ý rằng một khía cạnh của câu hỏi khiến tôi ngạc nhiên. Bạn viết:

// metadata[0], metadata[1], metadata[2] contain the BOM 

Thật là lạ khi ba byte đầu tiên của siêu dữ liệu XMP chứa BOM. Siêu dữ liệu XMP giả sử bắt đầu bằng <?xpacket. Nếu không, bạn đang làm điều đúng bằng cách loại bỏ các byte đó.

Lưu ý: PDF có thể chứa siêu dữ liệu XMP ở các cấp khác nhau. Ngay bây giờ, bạn đang kiểm tra một trong những phổ biến nhất: siêu dữ liệu cấp tài liệu. Bạn có thể gặp phải các tệp PDF có siêu dữ liệu XMP cấp trang, với XMP bên trong một hình ảnh, v.v ...

+0

* Quan sát thứ hai: dấu thứ tự byte không phải là một phần của tiêu đề. Đó là giá trị của thuộc tính bắt đầu * - đó là cách nó nên. Nhưng nếu tôi nhớ chính xác, mẫu đã ký và tệp được mã hóa của OP thực sự đã có BOM, xem [tại đây] (http://i.stack.imgur.com/nrj3t.png). (Tôi thực sự muốn xem xét vấn đề đó nhưng bị mất vấn đề.) – mkl

+0

Ý tôi là: nó không phải là một phần của tiêu đề PDF. Tiêu đề PDF trông như sau: '% PDF-1.'. Tôi sẽ làm rõ. –

+0

Tôi đã đọc lại câu hỏi. Đó là mơ hồ. Nó nói rằng BOM là một phần của tiêu đề của * file *, nhưng ví dụ cho thấy điều này không đúng: BOM được tìm thấy trong siêu dữ liệu XMP. Siêu dữ liệu XMP được bao bọc bên trong luồng bên trong tệp PDF. –

1

Chỉ cần một cách tiếp cận nhanh:

Đầu tiên: lưu cả hai tệp chưa được mã hóa. Thứ hai: xóa siêu dữ liệu 0 đến 2 trước khi lưu tệp

Tuy nhiên, có một số cân nhắc: phương pháp ký có yêu cầu BOM không? Phương thức mã hóa có yêu cầu BOM không?

Bạn cũng sẽ phải xác định ở giai đoạn nào BOM được thêm trước khi bạn có thể xác định xem bạn có thể/nên loại bỏ BOM không.

Tôi sẽ tìm hiểu nhanh về tài liệu cấu trúc pdf của mình và xem những gì tôi có thể nhận được, tuy nhiên cách đơn giản nhất sẽ là (chưa đọc) tải toàn bộ nội dung dưới dạng mảng byte và chỉ cần xóa xEF xBB xBF từ đầu tệp , sau đó thực hiện bất kỳ ký/mã hóa nào. Tuy nhiên họ có thể thêm nó vào một lần nữa ...

tôi sẽ đăng một bản cập nhật cuối tuần qua :)

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