19

I'm trying get a 206 response from my server using Android.

Here's the code.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);
    new AsyncTask<Void, Void, Void>() {
        @Override
        protected Void doInBackground(Void... params) {
            try {
                URL url = new URL("http://aviddapp.com/10mb.file");
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setRequestProperty("Range", "bytes=1-2");
                urlConnection.connect();

                System.out.println("Response Code: " + urlConnection.getResponseCode());
                System.out.println("Content-Length: " + urlConnection.getContentLength());
                Map<String, List<String>> map = urlConnection.getHeaderFields();
                for (Map.Entry<String, List<String>> entry : map.entrySet()) {
                    System.out.println("Key : " + entry.getKey() +
                            " ,Value : " + entry.getValue());
                }
                InputStream inputStream = urlConnection.getInputStream();
                long size = 0;

                while(inputStream.read() != -1 )
                    size++;

                System.out.println("Downloaded Size: " + size);

            }catch(MalformedURLException mue) {
                mue.printStackTrace();
            }catch(IOException ioe) {
                ioe.printStackTrace();
            }
            return null;
        }
    }.execute();
}

Here's the output:

I/System.out: Respnse Code: 200
I/System.out: Content-Length: -1
I/System.out: Key : null ,Value : [HTTP/1.1 200 OK]
I/System.out: Key : Accept-Ranges ,Value : [bytes]
I/System.out: Key : Cache-Control ,Value : [max-age=604800, public]
I/System.out: Key : Connection ,Value : [Keep-Alive]
I/System.out: Key : Date ,Value : [Tue, 04 Oct 2016 07:45:22 GMT]
I/System.out: Key : ETag ,Value : ["a00000-53e051f279680-gzip"]
I/System.out: Key : Expires ,Value : [Tue, 11 Oct 2016 07:45:22 GMT]
I/System.out: Key : Keep-Alive ,Value : [timeout=5, max=100]
I/System.out: Key : Last-Modified ,Value : [Tue, 04 Oct 2016 07:36:42 GMT]
I/System.out: Key : Server ,Value : [Apache/2.4.12 (Unix) OpenSSL/1.0.1e-fips mod_bwlimited/1.4]
I/System.out: Key : Transfer-Encoding ,Value : [chunked]
I/System.out: Key : Vary ,Value : [Accept-Encoding,User-Agent]
I/System.out: Key : X-Android-Received-Millis ,Value : [1475567127403]
I/System.out: Key : X-Android-Response-Source ,Value : [NETWORK 200]
I/System.out: Key : X-Android-Sent-Millis ,Value : [1475567127183]
I/System.out: Downloaded Size: 10485760

Now I'm doing the same thing is pure java.

public static void main(String... args) {
    try {
        URL url = new URL("http://aviddapp.com/10mb.file");
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setRequestProperty("Range", "bytes=1-2");
        urlConnection.connect();

        System.out.println("Respnse Code: " + urlConnection.getResponseCode());
        System.out.println("Content-Length: " + urlConnection.getContentLength());
        Map<String, List<String>> map = urlConnection.getHeaderFields();
        for (Map.Entry<String, List<String>> entry : map.entrySet()) {
            System.out.println("Key : " + entry.getKey() +
                    " ,Value : " + entry.getValue());
        }
        InputStream inputStream = urlConnection.getInputStream();
        long size = 0;

        while(inputStream.read() != -1 )
            size++;

        System.out.println("Downloaded Size: " + size);

    }catch(MalformedURLException mue) {
        mue.printStackTrace();
    }catch(IOException ioe) {
        ioe.printStackTrace();
    }
}

Here's the output

Respnse Code: 206
Content-Length: 2
Key : Keep-Alive ,Value : [timeout=5, max=100]
Key : null ,Value : [HTTP/1.1 206 Partial Content]
Key : Server ,Value : [Apache/2.4.12 (Unix) OpenSSL/1.0.1e-fips mod_bwlimited/1.4]
Key : Content-Range ,Value : [bytes 1-2/10485760]
Key : Connection ,Value : [Keep-Alive]
Key : Last-Modified ,Value : [Tue, 04 Oct 2016 07:36:42 GMT]
Key : Date ,Value : [Tue, 04 Oct 2016 07:42:17 GMT]
Key : Accept-Ranges ,Value : [bytes]
Key : Cache-Control ,Value : [max-age=604800, public]
Key : ETag ,Value : ["a00000-53e051f279680"]
Key : Vary ,Value : [Accept-Encoding,User-Agent]
Key : Expires ,Value : [Tue, 11 Oct 2016 07:42:17 GMT]
Key : Content-Length ,Value : [2]
Downloaded Size: 2

As you can see I'm getting diffrent response codes in both cases. It seems like Android is not passing Range to the server maybe? What's happening here?

PS: I'm getting a 206 if the file size is 1mb.

Binoy Babu
  • 16,699
  • 17
  • 91
  • 134
  • @EJP Can you take a look at this? – Binoy Babu Oct 04 '16 at 08:36
  • @NicolasFilotto can you take a look at this? – Binoy Babu Oct 04 '16 at 08:36
  • give us headers of both requests as well – klimat Oct 11 '16 at 07:19
  • Are you positive that the error is in the client? The server might be sending spurious results. Have you tried any other servers? I tried using Postman, and the server did not return a partial file. http://i.imgur.com/IbBqEll.png (edit: worth noting, I used this same system on a different server, where it worked, so the Postman config works) – Knossos Oct 11 '16 at 10:46
  • @mklimek Check the java code. – Binoy Babu Oct 11 '16 at 11:44
  • @binoy-babu check my answer please. – silentsudo Oct 11 '16 at 14:17
  • on which version of android are you running it ? – Blackbelt Oct 12 '16 at 15:08
  • I use Range requests with HttpUrlConnection in Android. Works fine for me so should work for you too. Something's wrong with your code or your server. – Fedor Oct 15 '16 at 07:21
  • Hi, I'm just run your code but for download another file (http://speedtest.ftp.otenet.gr/files/test10Mb.db) and I get 206 error as expected, so It looks like the problem is on the server side. – Roman_D Oct 17 '16 at 20:26

4 Answers4

6

I am relatively certain the error is not in the Android code.

It looks like the server might be delivering spurious results.

You can check with a third party tool (such as Postman) to determine the headers that web service is delivering.

My results using Postman. As you can see, it is delivering HTTP 200 (not 206). It is also not wending a capped Content-Length. If the server is yours, perhaps check that it is configured correctly. Also check your code with other servers.

Postman results

Knossos
  • 15,802
  • 10
  • 54
  • 91
5

Hi Can u try this piece of code, it seems i am getting HTTP 206 here.

new Thread() {
            @Override
            public void run() {
                try {
                    URL url = new URL("http://aviddapp.com/10mb.file");
                    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//                    urlConnection.setRequestMethod("HEAD");
                    urlConnection.setRequestProperty("Accept-Encoding", "");

                    urlConnection.setRequestProperty("Range", "bytes=1-2");
                    urlConnection.connect();

                    System.out.println("Response Code: " + urlConnection.getResponseCode());
                    System.out.println("Content-Length: " + urlConnection.getContentLength());
                    Map<String, List<String>> map = urlConnection.getHeaderFields();
                    for (Map.Entry<String, List<String>> entry : map.entrySet()) {
                        System.out.println("Key : " + entry.getKey() +
                                " ,Value : " + entry.getValue());
                    }
                    InputStream inputStream = urlConnection.getInputStream();
                    long size = 0;

                    while (inputStream.read() != -1)
                        size++;

                    System.out.println("Downloaded Size: " + size);

                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }.start();

You just have to add this in async task.

Check this result commenting on/off this line.

urlConnection.setRequestProperty("Accept-Encoding", "");
silentsudo
  • 6,730
  • 6
  • 39
  • 81
3

I am not sure if this is related to Content-Length being cleared by android implementation by default. Look at the below snippet from the source code where it says it does gzip compression by default.

https://android.googlesource.com/platform/libcore/+/2e317a02b5a8f9b319488ab9311521e8b4f87a0a/luni/src/main/java/java/net/HttpURLConnection.java

By default, this implementation of HttpURLConnection requests that servers use gzip compression and it automatically decompresses the data for callers of getInputStream(). The Content-Encoding and Content-Length response headers are cleared in this case.

Can you try disabling the default caching using below code to check if that works?

urlConnection.setRequestProperty("Accept-Encoding", "identity");

PS: Sorry for bad formattings. Using the mobile version of SO.

Shashank Kadne
  • 7,993
  • 6
  • 41
  • 54
1

Have you tried like that:

    urlConnection.setRequestProperty("Range", "bytes=1000-");
Fedor
  • 43,261
  • 10
  • 79
  • 89