汇众了下可能出问题的地方:
一,因为urlconnection会将大于2G的文件采用gzip进行压缩。然后getContentLength返回的是读取的长度,而不是总长度。类似于我们读取文件的时候使用length。到了文件末尾就返回-1.所以取消gzip压缩可以解决这个问题,就是我们需要设置如下代码:
conn.setRequestProperty("Accept-Encoding", "identity");
二,加上了上面的设置后,我发现我的问题也没解决。然后顺着代码读下去到这:
/** * Returns the value of the {@code content-length} header field. * <P> * <B>Note</B>: {@link #getContentLengthLong() getContentLengthLong()} * should be preferred over this method, since it returns a {@code long} * instead and is therefore more portable.</P> * * @return the content length of the resource that this connection's URL * references, {@code -1} if the content length is not known, * or if the content length is greater than Integer.MAX_VALUE. */ public int getContentLength() { long l = getContentLengthLong(); if (l > Integer.MAX_VALUE) return -1; return (int) l; }
可以看到,如果文件长度大于Int的最大值(2147483647),就返回-1,而我要下载的文件长度大于这个值的所以就返回了-1。不知道为啥这么做。是不是要兼容旧版本?一开始使用的是int,然后突然发现是坑,所以将计就计了,强转成int。
然后下面有另一个方法:
/** * Returns the value of the {@code content-length} header field as a * long. * * @return the content length of the resource that this connection's URL * references, or {@code -1} if the content length is * not known. * @since 7.0 */ public long getContentLengthLong() { return getHeaderFieldLong("content-length", -1); }返回的是long类型的值。但是限制api24 也就是7.0才能使用,使用这个就没问题。
但是,低于7.0的怎么办呢?我们知道这些参数都是从响应头里拿的,既然系统的不能使用,那就自己拿。。
private long getContentSize(HttpURLConnection conn) { long contentSize = -1; if (conn == null) { return contentSize; } String contentLength = conn.getHeaderField("Content-Length"); if (contentLength != null && !TextUtils.isEmpty(contentLength)) { try { contentSize = Long.parseLong(contentLength); }catch (NumberFormatException e){ e.printStackTrace(); } } return contentSize; }
以上,问题解决。