5

I'm downloading an attachment using Java mail API and whenever there is a small change in network state, my app gets stuck and I have to restart it, it's not even crashing. This is the code snippet:

InputStream is = bodyPart.getInputStream();

String fileName = MimeUtility.decodeText(bodyPart.getFileName());

// Downloading the file
File f = new File(Constants.getPath() + fileName);
try {
    FileOutputStream fos;
    fos = new FileOutputStream(f);

    byte[] buf = new byte[8*1024];
    int bytesRead;

    while ((bytesRead = is.read(buf)) != -1) {
    fos.write(buf, 0, bytesRead);
    }
    fos.close();
}

What is the best way to deal with this issue? Thanks.

jam
  • 3,640
  • 5
  • 34
  • 50
Tsikon
  • 324
  • 1
  • 3
  • 14
  • 1
    Try to wrapper the input stream with `BufferedInputStream` and see if `skip()` method is supported here (Does it throw IOException or not). If yes, then you would have the ability to resume the previous download. – Eng.Fouad Jan 04 '13 at 11:06
  • Hi, thanks, It does throw IOException. Would you kindly tell me how can I resume previous download and how is it related to the fact that the app freezes? – Tsikon Jan 04 '13 at 13:12
  • If it supports `skip()`, then it would support `Resuming previous download`. However, the only option I can think of is to have a timeout on `is.read()`, and if it happens to exceed the timeout period, then you should terminate the download and start over again. See this SO question: http://stackoverflow.com/questions/804951/is-it-possible-to-read-from-a-inputstream-with-a-timeout – Eng.Fouad Jan 04 '13 at 13:31
  • @Eng.Fouad BufferedInputStream supports skip() all by itself: it doesn't need testing to establish that; but BufferedInputStream supporting skip() has nothing to do with JavaMail supporting resumption of a prior download. What he needs is a read timeout. I don't have the JavaMail documentation to hand but surely it supports that. – user207421 Jan 04 '13 at 18:24
  • @EJP [According to the documentation](http://docs.oracle.com/javase/6/docs/api/java/io/BufferedInputStream.html#skip(long)), `skip()` throws `IOException` if the stream does not support seek, and that's why I said "If it supports `skip()`, then it would support `Resuming previous download`". – Eng.Fouad Jan 04 '13 at 21:07
  • @Eng.Fouad Why? What does skip() have to do with resume? – user207421 Jan 04 '13 at 21:17
  • @EJP Doesn't `resume` require `seek`? – Eng.Fouad Jan 04 '13 at 21:44
  • @Eng.Fouad This is making less and less sense. Now I have to ask you what skip() has to do with seeking. You seem to think that skip() can go backwards. It can't. See the Javadoc you cited. I also repeat that BufferedInputStream supports skip() all by itself (see the course code), nothing to do with JavaMail. – user207421 Jan 04 '13 at 22:20
  • Duplicate of [How to properly set JavaMail timeout setting](http://stackoverflow.com/questions/4620102/how-to-properly-set-javamail-timeout-setting) – user207421 Jan 04 '13 at 22:26
  • @EJP Let's take an example. Suppose we download a file of size 100MB, and in the middle of the process (say at 50MB) the connection was down. Later, if the stream supports `seeking` feature, then we could `skip()` the first 50MB and resumes the download starting from 51st megabyte. Isn't this the purpose of using `skip()`? – Eng.Fouad Jan 05 '13 at 03:33
  • @Eng.Fouad His problem is that his application gets stuck. No amount of resuming or seeking or skipping is going to fix that. The entire discussion lacks relevance. It applies to what happens after he fixes his current problem. – user207421 Jan 05 '13 at 05:01

1 Answers1

1

Your application is stuck. The solution to that is to set a read timeout, as discussed in this question. If the timeout occurs a SocketTimeoutException will be thrown.

Community
  • 1
  • 1
user207421
  • 305,947
  • 44
  • 307
  • 483
  • I have all the following timeouts: props2.setProperty("mail.imaps.connectionpooltimeout", "3000"); props2.setProperty("mail.imaps.connectiontimeout", "3000"); props2.setProperty("mail.imap.timeout", "3000"); And still it stucks when getting Message details, for example message.getSubject(). Strangely it happens only when switching from 3g to WI-FI. When I switch from WI-FI to 3g it throws FolderClosedException and then I can handle this. – Tsikon Jan 05 '13 at 19:34
  • Thanks, I solved it by changing the imap to imaps in the timeout property. – Tsikon Jan 26 '13 at 14:02