Android中的HttpUrlConnection设置范围被忽略

我试图从我的服务器使用Android获得206响应。

这是代码。

@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(); } 

这是输出:

 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 

现在我做同样的事情是纯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(); } } 

这是输出

 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 

正如你所看到的,在这两种情况下我都得到了不同的响应代码。 看起来Android是不是将Range传递给服务器呢? 这里发生了什么事?

PS:如果文件大小为1mb,我会得到206。

Solutions Collecting From Web of "Android中的HttpUrlConnection设置范围被忽略"

我相对肯定的错误是不是在Android的代码。

它看起来像服务器可能会提供虚假的结果。

您可以使用第三方工具(如Postman)来确定Web服务正在传递的标头。

我的结果使用邮递员。 正如你所看到的,它提供了HTTP 200 (不是206 )。 这也不是一个封顶的Content-Length 。 如果服务器是你的,也许检查它是否configuration正确。 还请检查您的代码与其他服务器。

邮递员结果

嗨你可以尝试这段代码,看来我在这里得到了HTTP 206

 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(); 

你只需要添加这个asynchronous任务。

检查这个结果评论/closures这一行。

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

我不知道这是否与Android的默认情况下清除Content-Length有关。 从源代码看下面的代码片段,它说默认情况下它会执行gzip压缩。

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

默认情况下, HttpURLConnection这个实现请求服务器使用gzip压缩,并自动解压缩getInputStream()调用者的数据。 Content-Encoding和Content-Length响应头在这种情况下被清除。

你可以尝试禁用默认caching使用下面的代码来检查是否有效?

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

PS:抱歉格式不对。 使用SO的移动版本。

你有这样的尝试:

  urlConnection.setRequestProperty("Range", "bytes=1000-");