在使用HttpGet下載文件的時候,遇到一個比較坑的問題就是獲取文件大小.
無論是使用HttpURLConnection還是使用HttpClient最后返回的response中response.getEntity().getContentLength()的值始終是-1。
因為使用response的Header中就沒有Content-Length這個字段,
在Http 1.0及之前版本中,Content-Length字段可有可無。
在http1.1及之后版本。如果是keep alive,則Content-Length和Chunk必然是二選一。若是非keep alive,則和http1.0一樣,Content-Length可有可無。
header中如果有Transfer-Encoding(重點是Chunked模式),則在header中就不能有Content-Length,有也會被忽視,
如果head中有Content-Length,那么這個Content-Length既表示實體長度,又表示傳輸長度。如果實體長度和傳輸長度不相等(比如說設置了Transfer-Encoding),那么則不能設置Content-Length。如果設置了Transfer-Encoding,那么Content-Length將被忽視
有人說使用HttpURLConnection的時候需要設置conn.setRequestProperty("Accept-Encoding", "identity");
說是HttpURLConnection使用了gzip壓縮的方式,告訴服務器不要使用gzip壓縮,
由于我使用的是HttpClient來實現下載,及時設置了這個屬性,還是無法獲取文件大小。
最后發現服務端使用的javax.servlet.http.HttpServletResponse有個方法
public abstract void setContentLength(int paramInt);
這個方法可以用來返回文件的大小,response.setContentLength(((Long)file.length()).intValue());
注意file的大小不能為0;
這樣在客戶端就能通過response.getEntity().getContentLength()來得到文件的大小,
其實這樣有個問題就是由于setContentLength的參數是int類型的,int的最大值是2147483647,
也就是說只能返回約2G大小的文件的長度,這就有點郁悶了。
不過由于項目中不允許上傳那么大的文件,所以是滿足需求的。
使用HttpClient下載并計算下載進度部分代碼:
HttpClient client = SSLSocketFactoryEx.getNewHttpClient();
client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_TIMEOUT);
client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 60000);
//get請求加入參數
String content =null;
StringBuilder sb =new StringBuilder();
sb.append(remoteUrl);?
Iterator it =map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
? ? try {
????????sb.append("&").append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "utf-8"));
? ? }catch (UnsupportedEncodingException e) {
????????e.printStackTrace();
? ? }
}
content = sb.toString();
HttpGet get =new HttpGet(content);
try {
HttpResponse response = client.execute(get);
? ? ? ? int status = response.getStatusLine().getStatusCode();
? ? ? ? if (200 == status) {
????????????if (response.getEntity() ==null){
????????????????callback.onError("response error");
????????????}
? ? ? ? ? ? length = response.getEntity().getContentLength();
? ? ? ? ? ? localInputStream = response.getEntity().getContent();
? ? ? ? ? ? //在本地存儲文件
? ? ? ? ? ? File localFile =new File(localFilePath);
? ? ? ? ? ? localFileOutputStream =new FileOutputStream(localFile);
? ? ? ? ? ? int bufsize = CommonUtils.getDownloadBufSize(this.context);
? ? ? ? ? ? byte[] arrayOfByte =new byte[bufsize];
? ? ? ? ? ? while ((i = localInputStream.read(arrayOfByte)) != -1) {
????????????????rate += i;
? ? ? ? ? ? ? ? if (length >0) {
????????????????????int progress = (int) (rate *100L / length); ?//下載進度
? ? ? ? ? ? ? ? ? ? if (callback !=null) {
????????????????????????callback.onProgress(progress); ? //可以在回調中進行進度條更新
? ? ? ? ? ? ? ? ? ? }
????????????}
????????????localFileOutputStream.write(arrayOfByte, 0, i);
? ? ? }
????? callback.onSuccess(null);
? }else {
? ? ?if (callback !=null) {
? ? ?????callback.onError(null);
?????}
}
//后邊的資源釋放,異常捕獲都省略了 ,只展示部分代碼
希望對你有所幫助