Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/197.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java URLConnection getContentLength()正在返回负值_Java_Android_Httpurlconnection - Fatal编程技术网

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