4

I am trying to download a part of file given the download URL using setRequestProperty("Range","bytes=" + startbytes + "-" + endbytes); The following code snippet shows what I am trying to do.

protected String doInBackground(String... aurl) {
    int count;
    Log.d(TAG,"Entered");
    try {

        URL url = new URL(aurl[0]);
        HttpURLConnection connection =(HttpURLConnection) url.openConnection();

        int lengthOfFile = connection.getContentLength();

        Log.d(TAG,"Length of file: "+ lengthOfFile);

        connection.setRequestProperty("Range", "bytes=" + 0 + "-" + 1000);

The problem is that, an exception is being raised, which says "Cannot set request property after connection is made". Please help me resolve this issue.

tet
  • 105
  • 1
  • 7

2 Answers2

9

Option 1

If you do not need to know the content length:

[Beware, do not call the connection.getContentLength(). If you call that, you will get the exception. If you need to call it, then check the second option]

URL url = new URL(aurl[0]);
HttpURLConnection connection =(HttpURLConnection) url.openConnection();
connection.setRequestProperty("Range", "bytes=" + 0 + "-" + 1000);
//Note that, response code will be 206 (Partial Content) instead of usual 200 (OK)
if(connection.getResponseCode() == HttpURLConnection.HTTP_PARTIAL){
    //Your code here to read response data
}

Option 2

If you need to know the content length:

URL url = new URL(aurl[0]);
//First make a HEAD call to get the content length  
HttpURLConnection connection =(HttpURLConnection) url.openConnection();
connection.setRequestMethod("HEAD");
if(connection.getResponseCode() == HttpURLConnection.HTTP_OK){
    int lengthOfFile = connection.getContentLength();
    Log.d("ERF","Length of file: "+ lengthOfFile);
    connection.disconnect();

    //Now that we know the content lenght, make the GET call
    connection =(HttpURLConnection) url.openConnection();
    connection.setRequestMethod("GET");
    connection.setRequestProperty("Range", "bytes=" + 0 + "-" + 1000);
    //Note that, response code will be 206 (Partial Content) instead of usual 200 (OK)
    if(connection.getResponseCode() == HttpURLConnection.HTTP_PARTIAL){
        //Your code here to read response data

    }
}
Sarwar Erfan
  • 18,034
  • 5
  • 46
  • 57
  • I apologise for the error. Because I was getting error, I tried opening another connection. Even then same error persisted. Whiling uploading the snippet I have forgotten to remove that part. Now I have edited the question slightly. Please help me resolve this – tet May 28 '13 at 10:10
  • @tet : I have updated the answer according to your updated question. – Sarwar Erfan May 29 '13 at 04:37
4

Assuming you're using HTTP for the download, you'll want to use the HEAD http verb and RANGE http header.

HEAD will give you the filesize (if available), and then RANGE lets you download a byte range.

Once you have the filesize, divide it into roughly equal sized chunks and spawn download thread for each chunk. Once all are done, write the file chunks in the correct order.

If you don't know how to use the RANGE header, here's another SO answer that explains how: https://stackoverflow.com/a/6323043/1355166

[EDIT]

To make file into chunks use this, and start the downloading process,

private void getBytesFromFile(File file) throws IOException {
    FileInputStream is = new FileInputStream(file); //videorecorder stores video to file

    java.nio.channels.FileChannel fc = is.getChannel();
    java.nio.ByteBuffer bb = java.nio.ByteBuffer.allocate(10000);

    int chunkCount = 0;

    byte[] bytes;

    while(fc.read(bb) >= 0){
        bb.flip();
        //save the part of the file into a chunk
        bytes = bb.array();
        storeByteArrayToFile(bytes, mRecordingFile + "." + chunkCount);//mRecordingFile is the (String)path to file
        chunkCount++;
        bb.clear();
    }
}

private void storeByteArrayToFile(byte[] bytesToSave, String path) throws IOException {
    FileOutputStream fOut = new FileOutputStream(path);
    try {
        fOut.write(bytesToSave);
    }
    catch (Exception ex) {
        Log.e("ERROR", ex.getMessage());
    }
    finally {
        fOut.close();
    }
}
Community
  • 1
  • 1
Som
  • 1,514
  • 14
  • 21
  • Thank you for your instantaneous response. I have tried whatever you said. But it still throws the same exception. Can you suggest any other alternate ways of achieving this, I mean if a file size is 200MB then how I can I download a chunk from some starting location to another ending location? – tet May 28 '13 at 10:00