Java URLConnection getContentLength()正在返回负值
这是我的密码:Java URLConnection getContentLength()正在返回负值,java,android,httpurlconnection,Java,Android,Httpurlconnection,这是我的密码: url = paths[0]; HttpURLConnection connection = (HttpURLConnection) url.openConnection(); int length = connection.getContentLength(); // i get negetive length InputStream is = (InputStream) url.getContent(); byte[] imageData = new byte[length]
url = paths[0];
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int length = connection.getContentLength(); // i get negetive length
InputStream is = (InputStream) url.getContent();
byte[] imageData = new byte[length];
int buffersize = (int) Math.ceil(length / (double) 100);
int downloaded = 0;
int read;
while (downloaded < length) {
if (length < buffersize) {
read = is.read(imageData, downloaded, length);
} else if ((length - downloaded) <= buffersize) {
read = is.read(imageData, downloaded, length - downloaded);
} else {
read = is.read(imageData, downloaded, buffersize);
}
downloaded += read;
publishProgress((downloaded * 100) / length);
}
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0,
length);
if (bitmap != null) {
Log.i(TAG, "Bitmap created");
} else {
Log.i(TAG, "Bitmap not created");
}
is.close();
return bitmap;
url=path[0];
HttpURLConnection connection=(HttpURLConnection)url.openConnection();
int length=connection.getContentLength();//我得到负长度
InputStream为=(InputStream)url.getContent();
字节[]图像数据=新字节[长度];
int buffersize=(int)Math.ceil(长度/(双精度)100);
int=0;
int-read;
while(下载<长度){
if(长度<缓冲区大小){
read=is.read(图像数据,下载,长度);
}否则如果((length-download)简单的答案是内容长度未知。或者更具体地说,服务器没有在响应消息中设置“content length”头
您必须更改代码,以便它不会预先分配固定大小的字节数组来保存图像
- 另一种方法是通过tearrayoutputstream创建一个本地
并将从套接字读取的字节复制到该套接字。然后调用toByteArray
获取完整的字节数组
- 如果可以更改服务器端,另一种选择是在响应中设置content length标头。这必须在获取OutputStream将图像字节写入响应之前完成
您现有的代码在另一方面也被破坏。如果您得到IOException或其他异常,代码块将“异常退出”不关闭URLConnection。这将导致文件描述符泄漏。多次这样做,您的应用程序将因文件描述符或本地端口号耗尽而失败
最佳做法是使用try/finally确保绑定外部资源的URL连接、套接字、流等始终处于关闭状态。请参见此处:
上面说,
返回:
此连接的URL引用的资源的内容长度,如果内容长度未知,则为-1
这仅仅意味着标题不包含内容长度
字段。如果您对服务器代码有控制权,您应该以某种方式设置内容长度。类似于的内容,我在我的墙纸应用程序中也遇到了此问题。问题是因为您的服务器在其http标题中没有提供内容长度。下面是一个示例关于内容长度为的正常http头的快照
我正在使用共享主机,因此无法更改服务器配置。在我的应用程序中,我使用近似值(大于实际文件大小)设置了进度对话框最大值,如下所示:
int filesize = connection.getContentLength();
if(filesize < 0) {
progressDialog.setMax(1000000);
} else {
progressDialog.setMax(filesize);
}
int filesize=connection.getContentLength();
如果(文件大小<0){
progressDialog.setMax(1000000);
}否则{
progressDialog.setMax(文件大小);
}
您还可以在此处查看我的完整示例源代码:
.服务器在其响应头中似乎没有提供内容长度,您是否从响应头中获得了传输编码=分块头
我的情况是:我执行一个<强> HTTURL连接< /强>,并考虑服务器将响应我的“内容长度”的正值,但它没有,然后我转向
AndroidHttpClient哪个android HttpClient实现,再次执行相同的请求并获得正确的内容长度
我使用Wireshark分析了这两个请求,发现请求头有点不同
使用AndroidHttpClient的标题列表:
---------------------------------- request headers
Range : bytpe=0-
Host : download.game.yy.com
Connection : Keep-Alive
User-Agent : com.duowan.mobile.netroid
---------------------------------- response headers
Server : nginx
Content-Type : text/plain; charset=utf-8
ETag : "535e2578-84e350"
Cache-Control : max-age=86400
Accept-Ranges : bytes
Content-Range : bytes 0-8708943/8708944
Content-Length : 8708944
使用HttpURLConnection的请求标头列表:
---------------------------------- request headers
Range : bytpe=0-
Host : download.game.yy.com
Connection : Keep-Alive
User-Agent : com.duowan.mobile.netroid
Accept-Encoding : gzip // difference here
---------------------------------- response headers
Server : nginx
Content-Type : text/plain; charset=utf-8
Cache-Control : max-age=86400
Transfer-Encoding : chunked
X-Android-Received-Millis : 1398861612782
X-Android-Sent-Millis : 1398861608538
与请求头的唯一区别是接受编码,这不是我自己添加的,它是Android的默认设置,之后,我将其设置为标识,然后再次执行请求,下面是完整的头堆栈:
---------------------------------- request headers
Range : bytpe=0-
Host : download.game.yy.com
Connection : Keep-Alive
User-Agent : com.duowan.mobile.netroid
Accept-Encoding : identity
---------------------------------- response headers
Server : nginx
Content-Type : text/plain; charset=utf-8
ETag : "535e2578-84e350"
Cache-Control : max-age=86400
Accept-Ranges : bytes
Content-Range : bytes 0-8708943/8708944
Content-Length : 8708944
X-Android-Received-Millis : 1398862186902
X-Android-Sent-Millis : 1398862186619
如您所见,在我将Accept编码设置为“identity”替换系统默认值“gzip”后,服务器提供了“Content Length”正数,这就是为什么AndroidHttpClient可以使用正确的Content Length值,而HttpURLConnection不能
GZIP压缩编码可能会导致服务器端考虑的块响应,如果服务器认为可以接收块编码响应,则可能不提供<强>内容长度< /强>报头,尝试禁用GZIP可接受的行为,然后查看与此有什么不同。默认情况下,
< P> > HTTP连接的实现服务器使用gzip压缩的请求。
由于getContentLength()返回传输的字节数,因此无法使用该方法预测可以从getInputStream()读取多少字节。
相反,当read()返回-1时,读取该流直到其耗尽。
通过在请求头中设置可接受的编码,可以禁用Gzip压缩:
urlConnection.setRequestProperty("Accept-Encoding", "identity");
所以试试这个:
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Accept-Encoding", "identity"); // <--- Add this line
int length = connection.getContentLength(); // i get negetive length
HttpURLConnection connection=(HttpURLConnection)url.openConnection();
connection.setRequestProperty(“接受编码”、“标识”);//您在应用程序或服务器端向我推荐的任何更改。我需要在此添加的任何代码我确实捕获到了异常,我并没有在上面发布该代码,上面的所有代码都驻留在try catch语句中。这不仅仅是捕获异常的问题。您必须在finally blo中关闭连接同样是ck。嗨,我已经添加了我在编辑中使用的方法的完整代码。是的。我明白了。正如我所期望的(正如我上面解释的),如果在打开连接和关闭InputStream之间引发异常,则代码可能会泄漏套接字文件描述符。此连接的URL引用的资源的内容长度,如果内容长度未知,则为-1。请注意:关闭传输编码可能会导致服务器上的性能问题,因为大多数它可能不再能够“流式”处理您请求的任何内容,并且必须在发送之前“计算”整个响应
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Accept-Encoding", "identity"); // <--- Add this line
int length = connection.getContentLength(); // i get negetive length