Android 中的 HttpUrlConnection 设置范围被忽略
HttpUrlConnection setting Range in Android is ignored
我正在尝试使用 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。
我比较确定错误不在 Android 代码中。
看起来服务器可能提供了虚假结果。
您可以检查 third party tool (such as Postman) 以确定 Web 服务正在传送的 headers。
我使用 Postman 的结果。如您所见,它正在交付 HTTP 200
(而不是 206
)。它也没有达到上限 Content-Length
。如果服务器是您的,也许检查它是否配置正确。还要检查您与其他服务器的代码。
我不确定这是否与 Content-Length
默认被 android 实现清除有关。从源代码中查看下面的片段,它说它默认执行 gzip 压缩。
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.
您可以尝试使用以下代码禁用默认缓存以检查是否有效吗?
urlConnection.setRequestProperty("Accept-Encoding", "identity");
PS: 抱歉格式错误。使用手机版SO.
你好,你能试试这段代码吗,看来我在这里 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();
你只需要在异步任务中添加它。
检查此结果评论 on/off 这一行。
urlConnection.setRequestProperty("Accept-Encoding", "");
你试过吗:
urlConnection.setRequestProperty("Range", "bytes=1000-");
我正在尝试使用 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。
我比较确定错误不在 Android 代码中。
看起来服务器可能提供了虚假结果。
您可以检查 third party tool (such as Postman) 以确定 Web 服务正在传送的 headers。
我使用 Postman 的结果。如您所见,它正在交付 HTTP 200
(而不是 206
)。它也没有达到上限 Content-Length
。如果服务器是您的,也许检查它是否配置正确。还要检查您与其他服务器的代码。
我不确定这是否与 Content-Length
默认被 android 实现清除有关。从源代码中查看下面的片段,它说它默认执行 gzip 压缩。
By default, this implementation of
HttpURLConnection
requests that servers use gzip compression and it automatically decompresses the data for callers ofgetInputStream()
. The Content-Encoding and Content-Length response headers are cleared in this case.
您可以尝试使用以下代码禁用默认缓存以检查是否有效吗?
urlConnection.setRequestProperty("Accept-Encoding", "identity");
PS: 抱歉格式错误。使用手机版SO.
你好,你能试试这段代码吗,看来我在这里 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();
你只需要在异步任务中添加它。
检查此结果评论 on/off 这一行。
urlConnection.setRequestProperty("Accept-Encoding", "");
你试过吗:
urlConnection.setRequestProperty("Range", "bytes=1000-");