2008-08-21 33 views
95

Tôi có hai ứng dụng được viết bằng Java giao tiếp với nhau bằng cách sử dụng các thông điệp XML qua mạng. Tôi đang sử dụng trình phân tích cú pháp SAX ở đầu nhận để lấy dữ liệu ra khỏi thư. Một trong những yêu cầu là nhúng dữ liệu nhị phân vào một tin nhắn XML, nhưng SAX không thích điều này. Có ai biết cách để làm điều này không?Làm cách nào để nhúng dữ liệu nhị phân trong XML?

CẬP NHẬT: Tôi đã làm việc này với lớp Base64 từ apache commons codec library, trong trường hợp bất kỳ ai khác đang cố gắng tương tự.

+3

Genius! Chỉ cần những gì tôi đang tìm kiếm! –

Trả lời

192

Bạn có thể mã hóa dữ liệu nhị phân bằng base64 và đặt nó vào phần tử Base64; bài viết dưới đây là một bài viết khá hay về chủ đề này.

Handling Binary Data in XML Documents

+0

Hãy cẩn thận, một số tường lửa (https-kết nối) dường như đôi khi chặn khi ký tự "=" hiện diện. (Nhiều mã hóa chuỗi kết quả trong một cái gì đó như thế "kdiLKjdfdilfse =") – tObi

4

Có thể mã hóa chúng thành một tập hợp đã biết - giống như cơ số 64 là một lựa chọn phổ biến.

5

Thử mã hóa Base64/giải mã dữ liệu nhị phân của bạn. Cũng xem xét các phần CDATA

190

XML là rất linh hoạt ...

<DATA> 
    <BINARY> 
    <BIT index="0">0</BIT> 
    <BIT index="1">0</BIT> 
    <BIT index="2">1</BIT> 
    ... 
    <BIT index="n">1</BIT> 
    </BINARY> 
</DATA> 

XML cũng giống như bạo lực - Nếu nó không giải quyết được vấn đề của bạn, bạn không sử dụng đủ của nó.

EDIT:

BTW: Base64 + CDATA có lẽ là giải pháp tốt nhất

(EDIT2:.
Ai upmods tôi, xin vui lòng cũng upmod câu trả lời thực Chúng tôi không muốn bất kỳ linh hồn nghèo đến Ở đây và thực sự thực hiện phương pháp của tôi bởi vì nó được xếp hạng cao nhất trên SO, phải không?)

+0

Tôi chỉ lặp lại câu nói đó cho bạn của tôi, và sau khi anh ấy cười, anh ấy nói "và thật đau đớn nếu hướng đến bạn" :) – kaybenleroll

+5

. một cách sử dụng XML hoàn toàn đáng hổ thẹn nếu bạn nghiêm túc. Và nếu bạn không, làm thế nào người mới bắt đầu, những người không viết-cao cấp-nghĩ-mức thấp biết? –

+1

Jeremy ...cho một chàng trai trẻ 23 tuổi, bạn vô cùng nghiêm túc/theo nghĩa đen ... bạn rõ ràng đã không làm việc đủ lâu trong ngành để xem tại sao đây là một câu trả lời thú vị với một câu chuyện cảnh báo cho sự dũng cảm giữa các dòng. – Kev

22

Base64 thực sự là câu trả lời đúng nhưng CDATA không, đó là cơ bản nói: "điều này có thể là bất cứ điều gì", tuy nhiên nó phải không chỉ là bất cứ điều gì, nó phải là Dữ liệu nhị phân được mã hóa Base64. Lược đồ XML định nghĩa Base 64 binary as a primitive datatype mà bạn có thể sử dụng trong xsd của mình.

+1

Điểm bổ sung để đề cập đến kiểu dữ liệu 'xs: base64Binary', là loại quyền sử dụng. –

2

Bạn cũng có thể Uuencode dữ liệu nhị phân gốc của mình. Định dạng này lớn hơn một chút nhưng nó cũng giống như mã hóa base63.

3

Bất kỳ binary-to-text encoding sẽ thực hiện thủ thuật. Tôi sử dụng một cái gì đó như thế

<data encoding="yEnc> 
<![CDATA[ encoded binary data ]]> 
</data> 
9

Tôi đã gặp sự cố này chỉ trong tuần trước. Tôi đã phải serialize một tập tin PDF và gửi nó, bên trong một tập tin XML, đến một máy chủ.

Nếu bạn đang sử dụng .NET, bạn có thể chuyển đổi tệp nhị phân trực tiếp thành chuỗi base64 và dán nó bên trong phần tử XML.

string base64 = Convert.ToBase64String(File.ReadAllBytes(fileName)); 

Hoặc, có phương pháp được tích hợp ngay vào đối tượng XmlWriter.Trong trường hợp đặc biệt của tôi, tôi đã phải bao gồm không gian tên datatype của Microsoft:

StringBuilder sb = new StringBuilder(); 
System.Xml.XmlWriter xw = XmlWriter.Create(sb); 
xw.WriteStartElement("doc"); 
xw.WriteStartElement("serialized_binary"); 
xw.WriteAttributeString("types", "dt", "urn:schemas-microsoft-com:datatypes", "bin.base64"); 
byte[] b = File.ReadAllBytes(fileName); 
xw.WriteBase64(b, 0, b.Length); 
xw.WriteEndElement(); 
xw.WriteEndElement(); 
string abc = sb.ToString(); 

Chuỗi abc trông cái gì đó trông như thế này:

<?xml version="1.0" encoding="utf-16"?> 
<doc> 
    <serialized_binary types:dt="bin.base64" xmlns:types="urn:schemas-microsoft-com:datatypes"> 
     JVBERi0xLjMKJaqrrK0KNCAwIG9iago8PCAvVHlwZSAvSW5mbw...(plus lots more) 
    </serialized_binary> 
</doc> 
0

Dưới đây là một ví dụ tốt về cách thức tiến hành XEP-0239

PS: đừng quên đọc Mo's answer.

PS2: đọc phần THÔNG BÁO trên XEP.

2

Không sử dụng mã hóa base64 vì nó tăng lượng dữ liệu bạn cần để lưu trữ ít nhất 40%. Thay vì sử dụng các phương thức mã hóa khác như yEnc.

+1

@Jamine vì vậy bạn có lựa chọn nào khác không? – Hunt

3

Chi phí cơ sở 64 là 33%.

BaseXML cho XML1.0 chi phí chỉ 20%. Nhưng nó không phải là một tiêu chuẩn và chỉ có một thực hiện C được nêu ra. Kiểm tra xem bạn có quan tâm đến kích thước dữ liệu hay không. Lưu ý rằng tuy nhiên các trình duyệt có xu hướng thực hiện nén để nó ít cần thiết hơn.

Tôi đã phát triển nó sau khi thảo luận trong chủ đề này: Encoding binary data within XML : alternatives to base64.

0

Nếu bạn có quyền kiểm soát định dạng XML, bạn nên chuyển vấn đề ra bên trong. Thay vì đính kèm XML nhị phân, bạn nên suy nghĩ về cách gửi kèm một tài liệu có nhiều phần, một phần chứa XML.

Giải pháp truyền thống cho mục đích này là bản lưu trữ (ví dụ: tar). Nhưng nếu bạn muốn giữ tài liệu kèm theo của mình ở định dạng dựa trên văn bản hoặc nếu bạn không có quyền truy cập vào thư viện lưu trữ tệp, cũng có lược đồ chuẩn được sử dụng nhiều trong email và HTTP là multipart/* MIME với Content-Transfer-Encoding: binary.

Ví dụ, nếu máy chủ của bạn giao tiếp thông qua HTTP và bạn muốn gửi một tài liệu nhiều phần dữ liệu, chính là một tài liệu XML trong đó đề cập đến một dữ liệu nhị phân, các thông tin liên lạc HTTP có thể trông như thế này:

POST/HTTP/1.1 
Content-Type: multipart/related; boundary="qd43hdi34udh34id344" 
... other headers elided ... 

--qd43hdi34udh34id344 
Content-Type: application/xml 

<myxml> 
    <data href="cid:data.bin"/> 
</myxml> 
--qd43hdi34udh34id344 
Content-Id: <data.bin> 
Content-type: application/octet-stream 
Content-Transfer-Encoding: binary 

... binary data ... 
--qd43hdi34udh34id344-- 

Như trong ví dụ trên, XML tham chiếu đến dữ liệu nhị phân trong multipart kèm theo bằng cách sử dụng lược đồ URI cid là định danh cho tiêu đề Content-Id. Chi phí của lược đồ này sẽ chỉ là tiêu đề MIME. Một lược đồ tương tự cũng có thể được sử dụng cho phản hồi HTTP. Tất nhiên trong giao thức HTTP, bạn cũng có tùy chọn gửi một tài liệu nhiều phần vào yêu cầu/phản hồi riêng biệt.

Nếu bạn muốn tránh gói dữ liệu của bạn trong một nhiều phần dữ liệu là sử dụng dữ liệu URI:

<myxml> 
    <data href="data:application/something;charset=utf-8;base64,dGVzdGRhdGE="/> 
</myxml> 

Nhưng điều này có overhead base64.

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