2014-04-11 3 views
0

Я использую javax.mail.internet.MimeBody * версии 1.4.1MimeBodyPart getContent развращает двоичные данные

Моя программа хочет отправить несколько двоичных данных с множественным уровнем вложенности от сервера к клиенту с помощью MimeMultiPart. Я заметил, что если на уровне, если мы используем GetContent, он искажает данные. Я был в состоянии воспроизвести эту проблему с этим фрагментом

public static void CreateResponse() throws Exception { 
     //Simulate the Server side 
     ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
     MimeMultipart multiPartValues = new MimeMultipart(); 
     MimeBodyPart valueBody = new MimeBodyPart(); 

     byte[] firstKeyValue = new byte[] { (byte)0x8c}; 
     valueBody.setContent(firstKeyValue,"application/octet-stream"); 
     valueBody.addHeader(RestMessageHeaders.CONTENT_LENGTH, 
       Integer.toString(firstKeyValue.length)); 
     multiPartValues.addBodyPart(valueBody); 

     Object input = valueBody.getContent(); 
     System.out.println(String.format("input %02X", ((byte[])input)[0])); 
     multiPartValues.writeTo(outputStream); 

     //Simulate the client side 
     byte[] mimeOutput = outputStream.toByteArray(); 

     ByteArrayDataSource ds = new ByteArrayDataSource(mimeOutput, 
       "multipart/mixed"); 
     MimeMultipart mp = new MimeMultipart(ds); 
     MimeBodyPart part = (MimeBodyPart) mp.getBodyPart(0); 

     byte[] myOutput = new byte[1]; 
     //Verified that getContent returns a String, why ?? 
     Object output = part.getContent(); 
     System.out.println("getContent type " + output.getClass()); 
     String result = (String)output; 
     ByteArrayDataSource partDS = new ByteArrayDataSource(result, "multipart/mixed"); 
     partDS.getInputStream().read(myOutput); 
     System.out.println(String.format("getContent %02X %02X", result.getBytes()[0],result.getBytes()[1])); 
     System.out.println(String.format("getContent %02X", myOutput[0])); 

     part.getInputStream().read(myOutput); 
     System.out.println(String.format("getInputStream %02X", myOutput[0])); 

     part.getRawInputStream().read(myOutput); 
     System.out.println(String.format("getRawInputStream %02X", myOutput[0])); 

} 

Вот выход

 input 8C 
     getContent type class java.lang.String 
     getContent C2 8C 
     getContent C2 
     getInputStream 8C 
     getRawInputStream 8C 

Я полностью упростил код здесь, и это выглядит очевидным, чтобы использовать получить (Raw) InputStream, но у нас есть nestedMultiPart, а верхний уровень выполнял getContent, который в некоторых случаях приводил к сбою.

  1. Ввод типа байтового массива, но на клиенте getContent отвечает строкой. Сервер устанавливает контент в приложение/октет-поток, но на стороне клиента он выводится как строка. Что здесь происходит?
  2. Я не уверен, почему байт c2 добавлен до 8c. Что особенного в характере 8c?
  3. В чем разница между getInputStream и getRawInputStream. Когда использовать один над другим?

ответ

1

Что содержит полный поток, который создает сервер, и клиент читает?

Обратите внимание, что с помощью MimeMultipart без MimeMessage вы пропускаете некоторые из вещей, которые автоматически выполняются для вас MimeMessage, в частности вам не хватает вызова MimeMultipart.updateHeaders(). Поскольку метод защищен, вам необходимо подклассировать MimeMultipart и вызвать этот метод до вызова writeTo. Если это не устранит вашу проблему, покажите нам точные данные, которые записываются и читаются в потоке.

Как уже упоминалось выше, если вы ожидаете двоичные данные, вы почти наверняка хотите использовать getInputStream. GetRawInputStream дает вам данные до того, как они будут декодированы, например, вход base64 вместо двоичного вывода.

+0

У нас есть сервер с ключевыми значениями (Project Voldemort), и мы используем MimeMultiPart для передачи сообщения с сервера клиенту. Ключ и значение - это байтовые массивы. Мы используем MimeMultiPart для обработки сериализации/десериализации. Использует ли MimeMessage исправление? Также не уверен в последней строке. Вы имели в виду getInputStream для base64 и getRawInputStream для byteArray? –

+0

Это может быть больше, чем я могу объяснить в комментарии ... Есть части JavaMail, которые «ленивы». MimeMessage скрывает некоторые из вас. Если вы не используете MimeMessage, вам приходится иметь дело с этими аспектами самостоятельно. Прочтите javadocs для метода updateHeaders и дайте мне знать, если вы не понимаете. –

+0

Метод getInputStream возвращает декодированные данные. Он не имеет ничего общего с байтовыми массивами. GetRawInputStream возвращает закодированные данные. Он не имеет ничего общего с байтовыми массивами.Метод setContent может принимать байтовый массив, но метод getContent возвращает объект, соответствующий типу MIME. Если тип MIME не обрабатывается специально (например, типы текста), getContent просто вернет InputStream, и вам придется обрабатывать байты, как вы хотите. –

0

Не используйте getContent(), если он возвращает строку и вы хотите использовать двоичный файл. Строка не является контейнером для двоичных данных. Используйте getInputStream() и скопируйте байты.

+0

Желаю, чтобы все было просто, как вы говорите. Получить контент возвращает объект. До сериализации это был массив байтов, но после сериализации он возвращал строку. –

+0

Я не понимаю этот комментарий. Что не так просто в использовании getInputStream()? – EJP

+0

GetContent возвращает объект. До сериализации объект был байтовым массивом. Но после сериализации/де-сериализации объект был String. Поэтому GetContent не всегда неисправен. Также не уверен в различии между GetInputStream и GetRawInputStream. –

Смежные вопросы