问题
I use javax.mail.internet.MimeBody* version 1.4.1
My program wants to send some binary data with multiple level of nesting from a server to client using MimeMultiPart. I observed that if on a level if we use GetContent it corrupts the data. I was able to reproduce this problem with this snippet
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]));
}
Here is the output
input 8C
getContent type class java.lang.String
getContent C2 8C
getContent C2
getInputStream 8C
getRawInputStream 8C
I have completely simplified the code here and it looks obvious to use get(Raw)InputStream, but we have nestedMultiPart and the top level was doing getContent which caused it to fail for some cases.
- Input is of type byte Array, but on the client getContent responds with String. The server sets the content to application/octet-stream but on the client side it is outputted as string. What is going wrong here?
- I am not sure why the byte c2 is added before 8c. What is so special about the 8c character?
- What is the difference between getInputStream and getRawInputStream. When to use one over the another ?
回答1:
What does the complete stream contain that the server is creating and the client is reading?
Note that by using MimeMultipart without MimeMessage, you're missing some of the things that are done automatically for you by MimeMessage, in particular you're missing the call to MimeMultipart.updateHeaders(). Since the method is protected, you'll need to subclass MimeMultipart and call that method before calling writeTo. If that doesn't fix your problem, show us the exact data that's being written and read on the stream.
As mentioned above, if you're expecting binary data, you almost certainly want to use getInputStream. The getRawInputStream gives you the data before it has been decoded, e.g., the base64 input instead of binary output.
回答2:
Don't use getContent() if it returns a String and you want binary. String is not a container for binary data. Use getInputStream() and copy the bytes.
来源:https://stackoverflow.com/questions/23023583/mimebodypart-getcontent-corrupts-binary-data