Android gets error when I try to setRequestProperty to HttpURLConnection

I wrote a simple download manager and I am trying to set RESUME for all downloads. after googleing how to do it. I know there should be setRequestProperty

for the connection, but my code doesn't work and I get this error:

FATAL EXCEPTION: Thread-882
    java.lang.IllegalStateException: Cannot set request property after connection is made
            at libcore.net.http.HttpURLConnectionImpl.setRequestProperty(HttpURLConnectionImpl.java:510)

      

My code:

URL url = new URL(downloadPath);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

final int fileSize = connection.getContentLength();

File file = new File(filepath);
if (file.exists() && fileSize == file.length()) {
    return;
} else if (file.exists()) {
    connection.setRequestProperty("Range", "bytes="+(file.length())+"-");
}else
    connection.setRequestProperty("Range", "bytes=" + downloadedSize + "-");

connection.setRequestMethod("GET");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.connect();

      

how to solve this problem and set setRequestProperty

up the connection correctly ?

+3


source to share


3 answers


The problem is what you are calling connection.getContentLength()

before you are calling setRequestProperty()

. Content length is only available after you have made a request, after which you cannot set the request property ...

It is not entirely clear what you are trying to do, but one option is to use the query HEAD

only to get the length of the content, and then make a separate query if you only need to get a portion of the data. Be aware that it is possible that the length of the content will change between requests , sure.



However, I would prefer to store more metadata somewhere in your download manager, so that when you first start downloading data, you will keep a record of the total size, so you don’t have to make a HEAD

query when you resume - you can only specify from local information, whether you downloaded the file or not. (This has the same problem in terms of changing content, but that's a different matter.)

+1


source


I had the same error as OP.

Why The problem is that when you try to set parameters for a request to resume download, you must be disconnected from Http.

The moment you call the method connection.getContentLenght();

, the following happens: connection.connect();

so if you try to set connection properties you will get the mentioned error.

FIX What I did is that I closed the Http connection after I called the methodlong totalFileSize = connection.getContentLength();



connection.disconnect()

// Disconnect from http

And after that, you can set the parameters you want to connect and call connection.connect()

if needed.

Tip In my particular case, I was trying to download a file and was needed to support resumable downloads, so I did the following for that:

  • Check if the file exists.
  • If the file exists, then get the length of the file:

    long bytesDownloaded = file.getLenght();

  • Use this length to set it up on the connection so that it can resume at exactly the specified bytes.

  • Write bytes to the end of the file.

+1


source


  • You must set properties before getContentLength()

  • If you set the range to the existing length of the file, you will get the remaining bytes when called getContentLength()

    , so if the content length is "0" it means the file has been fully loaded.

But if you want to create a download manager, @ Jon Skeet's method would be smart.

Edit:

public abstract long getContentLength ()

Added in API Level 1 Reports the length of the content, if known.

Returns the number of bytes of the content, or negative if unknown. If the length of the content is known but exceeds Long.MAX_VALUE, a negative number is returned.

0


source







All Articles