HttpURLConnection getContentLength返回-1

本文详细解析了在使用HttpURLConnection时遇到getContentLength()返回-1的问题,并提供了多种解决方案,包括设置请求属性以避免服务器返回gzip压缩内容,以及如何通过Fiddler工具进行深入分析。

HttpURLConnection getContentLength返回-1

2017年10月30日 20:09:42 yifan42421 阅读数:1703更多

个人分类: android

解决方法:

 

urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Accept-Encoding", "identity");
urlConnection.setRequestProperty("User-Agent", " Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36");

 

 

全部源码:

 

 

 
  1. try {

  2. //打开链接

  3. URL url = new URL(strings[0]);

  4. HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

  5.  
  6. //必须加上下面三句,要不total为-1

  7. urlConnection.setRequestMethod("POST");

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

  9. urlConnection.setRequestProperty("User-Agent", " Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36");

  10.  
  11. if (200 == urlConnection.getResponseCode()) {

  12. Log.i(TAG, "200");

  13. //得到输入流

  14. InputStream is = urlConnection.getInputStream();

  15. ByteArrayOutputStream baos = new ByteArrayOutputStream();

  16. byte[] buffer = new byte[1024];

  17. int len = 0;

  18. int count = 0;

  19.  
  20. long total = urlConnection.getContentLength();

  21. Log.i(TAG, "total = " + total);

  22. while (-1 != (len = is.read(buffer))) {

  23. baos.write(buffer, 0, len);

  24. count += len;

  25. publishProgress((int) ((count / (float) total) * 100));

  26. Log.i(TAG, " baos = " + baos.toString("utf-8"));

  27. Thread.sleep(500);

  28. }

  29. Log.i(TAG, " baos = " + baos.toString("utf-8"));

  30. return baos.toString("utf-8");

  31. } else {

  32. Log.i(TAG, " 系统错误 code = " + urlConnection.getResponseCode());

  33. }

  34. } catch (MalformedURLException e) {

  35. Log.i(TAG, "URLException = " + e.toString());

  36. e.printStackTrace();

  37. } catch (IOException e) {

  38. Log.i(TAG, "IOException = " + e.toString());

  39. e.printStackTrace();

  40. } catch (InterruptedException e) {

  41. Log.i(TAG, "InterruptedException = " + e.toString());

  42. e.printStackTrace();

  43. }

 

 

 

参考链接:点击打开链接

 

获取网络大小使用的代码如下:

 

[java] view plain copy

  1. URL url=new   URL("http://yinyueshiting.baidu.com/data2/music/123296359/13132725248400128.mp3?xcode=bce09e68531be7afafd0ef4fac9a741419c56da7f7cc7a9f");     
  2. HttpURLConnection   urlcon=(HttpURLConnection)url.openConnection();     
  3. //根据响应获取文件大小   
  4. int   fileLength=urlcon.getContentLength(); //这里获取的是字节    
  5.  double fileLenM=Double.parseDouble(df.format((fileLength/1024.00)/1024.00)); //转为M  

 

 

正常情况下能获取到 文件的大小

如果返回 -1,原因可能有很多种

 

首先排除 链接不正确或者服务器响应的问题 或者ip被屏蔽

假设我现在要获取 

http://yinyueshiting.baidu.com/data2/music/123296359/13132725248400128.mp3?xcode=bce09e68531be7afafd0ef4fac9a741419c56da7f7cc7a9f

链接的mp3的大小

 

则把该链接在浏览器的下载任务中新建 尝试下载

 

 

 

如果能下载,则说明链接正确,服务器也没问题,ip也没被屏蔽也就是我们的代码有问题。

 

网上一些解决方案说是HttpURLConnection 使用 gzip方式获取 的原因。

加上代码

 

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

可以解决

 

详见

Android getContentLength()为-1 解决方法

 

 

如果上述方法仍然不行

 

那继续往下分析

我们在谷歌浏览器中访问这个链接

查看它的请求头以及response 发现response中是有content-length的 一般都会有

 

那我们的代码问题到底出在哪呢

 

一般可能是请求头的问题  导致被服务器拒绝访问了

 

我的就是这个原因

 

加上User-agent 伪装一下 伪装成浏览器 后就可以了

 

[java] view plain copy

  1. URL url;  
  2.                         url = new   URL();                            
  3.                         HttpURLConnection   urlcon=(HttpURLConnection)url.openConnection();     
  4.                         urlcon.setRequestProperty("User-Agent", " Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36");  
  5.                         urlcon.setConnectTimeout(15000);  
  6.                         urlcon.setReadTimeout(15000);  
  7.                         //根据响应获取文件大小   
  8.                         fileLength=urlcon.getContentLength();  
  9.                         System.out.println("get fileLen "+fileLength);  

 

 

如果还不能解决 那就得用fidder工具好好分析一下了

通过fidder分析 我们发出的请求头 request跟浏览器发出的 request 有哪些区别

 

浏览器的request很容易获取 

 

打开 fidder,fidder会自动获取到浏览器中输入的链接的 相关信息。

 

 

而我们代码 运行的request则需要在代码中 加 代理

指向本机的 fidder监听端口

工具----> fidder选项--->监听端口 可以查看端口

 

 

代码中加代理 

 

[java] view plain copy

  1. String host = "127.0.0.1";    
  2.      String port = "8888";    
  3.      setProxy(host, port);   
  4.      public static void setProxy(String host, String port) {    
  5.     System.setProperty("proxySet", "true");    
  6.     System.setProperty("proxyHost", host);    
  7.     System.setProperty("proxyPort", port);    
  8. }   

 

 

然后运行代码

fidder就能监听到 请求了 

 

对比一下 或者构造成跟 浏览器访问的一模一样 就绝对ok了

 

其实只要找到其中几个关键的 参数设置成一样的也是可以的

 

不同场景下返回值为 -1 有不同的解决办法,以下是一些常见情况: #### KCP 协议中 `ikcp_input` 返回 -1 当 `ikcp_input` 返回 -1 时,通常表示输入的数据长度不足,无法构成一个完整的 KCP 数据包。可以尝试累积后续数据以重新处理。示例代码如下: ```cpp #include "ikcp.h" // 假设已经创建了 kcp 控制块 ikcpcb *kcp; // 定义一个缓冲区用于累积数据 char buffer[4096]; int buffer_length = 0; // 接收到的数据 char received_data[1024]; int received_length = 10; // 假设接收到的数据长度 // 累积数据 if (buffer_length + received_length < sizeof(buffer)) { memcpy(buffer + buffer_length, received_data, received_length); buffer_length += received_length; } int result = ikcp_input(kcp, buffer, buffer_length); if (result == -1) { // 继续等待更多数据 } else { // 处理成功,清空缓冲区 buffer_length = 0; } ``` #### MyBatis 更新操作返回 -1 默认情况下,MyBatis 的 update 操作返回值是记录的 matched 的条数,并不是影响的记录条数。将 MyBatis 中的 executorType 修改成 BATCH 【批量模式】后,会让更新结果返回值变成 -1。若想获取影响的记录数,可尝试将 executorType 改回默认值[^2]。 #### QT + Oracle query 的 `size()` 返回 -1 对于 QT + Oracle 中 `query` 的 `size()` 返回 -1 的情况,目前没有明确通用的简洁解决办法。可能需要检查 SQL 语句是否正确,数据库连接是否正常等。例如: ```cpp QSqlQuery query; query.exec("select jh,dd from tjc_yjzt where cc1>0"); if (query.size() == -1) { // 检查 SQL 语句和数据库连接 qDebug() << "Query size is -1, check SQL and connection."; } ``` #### `HttpURLConnection` 的 `getContentLength()` 返回 -1 在做 AsyncTask 异步任务读取网络数据时,`HttpURLConnection` 的 `getContentLength()` 总是为 -1,导致进度条一直为灰色状态。可以通过其他方式来获取数据长度,例如读取响应头的其他字段或者分块读取数据。示例代码如下: ```java import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; public class Main { public static void main(String[] args) { try { URL url = new URL("http://example.com"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); int contentLength = connection.getContentLength(); if (contentLength == -1) { // 分块读取数据 // ... } } catch (IOException e) { e.printStackTrace(); } } } ``` #### iOS UDP `sendto` 方法返回 -1 在 iOS 中,UDP `sendto` 方法返回 -1 可能是因为没有允许广播。在发送广播前,需要允许广播,示例代码如下: ```objc #import <Foundation/Foundation.h> #import <sys/socket.h> #import <netinet/in.h> #import <arpa/inet.h> @interface UDPManager : NSObject @property (nonatomic, strong) GCDAsyncUdpSocket *udpSocket; @end @implementation UDPManager - (instancetype)init { self = [super init]; if (self) { self.udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; NSError *error; if (![self.udpSocket enableBroadcast:YES error:&error]) { NSLog(@"enableBroadcast %@", error); } } return self; } @end ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值