2014-04-11 3 views
0

내가 javax.mail.internet.MimeBody * 1.4.1의 MimeBodyPart의 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 

이며 (원시)의 InputStream을 얻을 사용하는 것이 명백한 보이지만, 우리는이 nestedMultiPart 및 최상위 수준에서 getContent가 발생하여 일부 경우 실패하게되었습니다.

  1. 입력 형식은 바이트 배열이지만 클라이언트에서는 getContent가 String으로 응답합니다. 서버는 콘텐츠를 application/octet-stream으로 설정하지만 클라이언트 측에서는 문자열로 출력됩니다. 여기서 뭐가 잘못 됐어?
  2. 8c 앞에 바이트 c2가 추가 된 이유가 확실하지 않습니다. 8c 캐릭터에 대한 특별한 점은 무엇입니까?
  3. getInputStream과 getRawInputStream의 차이점은 무엇입니까? 언제 다른 것을 사용합니까?

답변

1

전체 스트림에는 서버가 만들고 클라이언트가 읽고있는 내용이 무엇입니까?

MimeMultipart를 MimeMessage없이 사용하면 MimeMessage에서 자동으로 수행 한 작업 중 일부가 누락됨을 알 수 있습니다. 특히 MimeMultipart.updateHeaders() 호출이 누락되었습니다. 이 메서드는 보호되어 있으므로 writeTo를 호출하기 전에 MimeMultipart를 서브 클래 싱하고 해당 메서드를 호출해야합니다. 그래도 문제가 해결되지 않으면 스트림에 쓰여지고 읽혀진 정확한 데이터를 표시하십시오.

위와 같이 바이너리 데이터가 필요하다면 getInputStream을 사용하는 것이 좋습니다. getRawInputStream은 디코딩 된 데이터 (예 : 바이너리 출력 대신 base64 입력)를 제공합니다.

+0

우리는 핵심 가치 서버 (Project Voldemort)를 보유하고 있으며 MimeMultiPart를 사용하여 서버에서 클라이언트로 메시지를 전송합니다. 키와 값은 바이트 배열입니다. 우리는 MimeMultiPart를 사용하여 직렬화/직렬화를 처리하고 있습니다. MimeMessage를 사용하여 수정합니까? 마지막 줄에 대해서도 확실하지 않습니다. base64의 경우 getInputStream을, byteArray의 경우 getRawInputStream을 사용 하시겠습니까? –

+0

이것은 설명에서 설명 할 수있는 것보다 오래 걸릴 수 있습니다 ... "게으른"JavaMail의 일부가 있습니다. MimeMessage는 그 중 일부를 숨 깁니다. MimeMessage를 사용하지 않는다면, 당신은 그 측면을 직접 처리해야합니다. updateHeaders 메소드에 대한 javadoc을 읽고 이해할 수없는 경우 알려주십시오. –

+0

getInputStream 메소드는 디코드 된 데이터를 리턴합니다. 바이트 배열과는 아무런 관련이 없습니다. getRawInputStream은 인코딩 된 데이터를 리턴합니다. 바이트 배열과는 아무런 관련이 없습니다.setContent 메소드는 바이트 배열을 허용하지만 getContent 메소드는 MIME 유형에 적합한 객체를 리턴합니다. MIME 유형이 특별히 처리되지 않으면 (예 : 텍스트 유형이 그렇듯이) getContent는 InputStream을 리턴하고 사용자가 원하는대로 바이트를 처리해야합니다. –

0

문자열을 반환하고 이진수를 원할 경우 getContent()를 사용하지 마십시오. 문자열은 바이너리 데이터의 컨테이너가 아닙니다. getInputStream()을 사용하고 바이트를 복사하십시오.

+0

나는 당신이 말한 것처럼 간단했다. Get content는 객체를 반환합니다. 직렬화 이전에는 바이트 배열 이었지만 직렬화 후에는 문자열을 반환합니다. –

+0

이 의견을 이해할 수 없습니다. getInputStream() 사용에 대해 간단하지 않은 것은 무엇입니까? – EJP

+0

GetContent는 객체를 반환합니다. 직렬화 이전에 객체는 바이트 배열이었습니다. 그러나 serialization/de-serialization 후 Object는 String입니다. 따라서 GetContent가 항상 결함이있는 것은 아닙니다. GetInputStream과 GetRawInputStream의 차이점에 대해서도 확실하지 않습니다. –