Search code examples
javahttpappletdownload

Download a large file over a HTTPConnection - JAVA Applet


This is probably a often asked question but I couldn't find a right answer yet.

Well, I've got the following code:

java.net.URL url = new java.net.URL(built);
java.net.HttpURLConnection con = (HttpURLConnection)url.openConnection();

if (con.getResponseCode() != 200) {
    // error handle here!;
    continue;
}

// begin to download the file
int file_size = con.getContentLength();

FileOutputStream stream = new FileOutputStream(m_WorkingDir + "/" + getFilenameWithPath(i));
InputStream remoteStream = con.getInputStream();

int chunks = (int) Math.ceil((float)file_size / (float)CHUNK_SIZE);

// download each chunk
byte[] temp = new byte[CHUNK_SIZE];
for(int a = 0; a < chunks; a++) {
    // calculate chunk size
    int chunk_size = CHUNK_SIZE;

    if(a == chunks-1) {
        // last chunk
        chunk_size = file_size - a * CHUNK_SIZE;
        System.out.println("Download last chunk : " + chunk_size);
    }

    // download chunk
    int bytes = remoteStream.read(temp, 0, chunk_size);
    stream.write(temp, 0 ,chunk_size); // save to local filesystem
}

stream.close();
remoteStream.close();
con.disconnect();

This code "should" simply download the file chunked.. but the point is that it doesn't do it correctly. I debugged the code and it turned out that it reads up to ~10 chunks correctly but then it reads like the half of chunk_size even if its not the last chunk, and then it returns -1 until the for(int a...) has finished.

To me it seems like the InputStream think it is EOF even if it is not! And yes I tested the HTTP Connection over a usual browser and it worked correctly.

It tested the code with multiple settings for CHUNK_SIZE but it had always the same result.

The file I want to download is about 10~Mbyte ..


Solution

  • You are assuming program to be downloading whole chunk size, but it may not be the case, because java says:-

    An attempt is made to read as many as len(CHUNK_SIZE) bytes, but a smaller number may be read, possibly zero.

    This may work:-

    byte[] temp = new byte[CHUNK_SIZE];
    int bytes = 0;
    for(int a = 0; a < chunks; a++) {
        bytes =remoteStream.read(temp, 0, CHUNK_SIZE);
        if(bytes == -1) {
          System.out.println("Downloaded last chunk : Terminating ");
          break;
        }
        stream.write(temp, 0 ,bytes);
    }