Jakarta mail could not read email photo
I don't know how to handle it.
InputStream x.available is 0 ,
Could not download source data
this is my writePart code
public static void writePart(Part p) throws MessagingException, IOException {
if (p.isMimeType("multipart/*")) {
Multipart content = (Multipart) p.getContent();
for (int i = 0; i < content.getCount(); i++) {
writePart(content.getBodyPart(i));
}
}
else if (p.isMimeType("text/*")) {
System.out.println(p.getContent());
}
else if (p.isMimeType("image/jpeg")) {
MimeBodyPart iPart = (MimeBodyPart) p;
String imgName = iPart.getFileName();
InputStream x = (InputStream) iPart.getContent();
//here!!! x.available is zore,why
System.out.println("x.length = " + x.available());
int i = 0;
byte[] bArray = new byte[x.available()];
while ((i = x.available()) > 0) {
int result = x.read(bArray);
if (result == -1)
break;
}
//todo temp directory
File file = new File("tmp/" + imgName);
boolean b = file.getParentFile().mkdirs();
FileOutputStream f2 = new FileOutputStream(file);
f2.write(bArray);
}
}
This is not the correct way to read an InputStream
. The documentation for InputStream.available
states:
Returns an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking by the next invocation of a method for this input stream. The next invocation might be the same thread or another thread. A single read or skip of this many bytes will not block, but may read or skip fewer bytes.
Note that while some implementations of
InputStream
will return the total number of bytes in the stream, many will not. It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream.
The key phrase there is "without blocking". This means there may be more data available on the remote side, so it's incorrect to use this to detect the end of the stream. Instead, you should check result
(the return value from InputStream.read
(bArray).
It's also incorrect to use the result from available
to allocate bArray
. It is not possible in general to determine the size of all data that will be produced by an InputStream
. In fact, regardless of the size of the buffer, it is not guaranteed that all of the data will be returned from the InputStream
in a single call to read
, so there needs to be a loop that either appends each read to a dynamically-sized buffer, or processes the read data in a streaming fashion. The latter is preferable, as it doesn't require retaining all of the data in memory at once, which could cause heap space exhaustion for large attachments in this case.
Implementing low-level I/O operations correctly can be tricky, so it's better to use a high-level method when available. In the case of MimeBodyPart
, you can use the writeTo
method to automatically write to the FileOutputStream
:
iPart.writeTo(f2);
This eliminates the need to explicitly get and read from the InputStream
.