Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android網絡編程之使用HttpClient批量上傳文件(二)AsyncTask+HttpClient並實現上傳進度監聽

Android網絡編程之使用HttpClient批量上傳文件(二)AsyncTask+HttpClient並實現上傳進度監聽

編輯:關於Android編程

請尊重他人的勞動成果,轉載請注明出處:

Android網絡編程之使用HttpClient批量上傳文件(二)AsyncTask+HttpClient並實現上傳進度監聽


運行效果圖:

AsyncTask+HttpClient並實現上傳進度監聽

我曾在《Android網絡編程之使用HttpClient批量上傳文件》一文中介紹過如何通過HttpClient實現多文件上傳和服務器的接收。在上一篇主要使用Handler+HttpClient的方式實現文件上傳。這一篇將介紹使用AsyncTask+HttpClient實現文件上傳並監聽上傳進度。

監控進度實現:

首先定義監聽器接口。如下所示:

/**
 * 進度監聽器接口
 */
public interface ProgressListener {
    public void transferred(longtransferedBytes);
}

實現監控進度的關鍵部分就在於記錄已傳輸字節數,所以我們需重載FilterOutputStream,重寫其中的關鍵方法,實現進度監聽的功能,如下所示,本例中首先重載的是HttpEntityWrapper,顧名思義,就是將需發送的HttpEntity打包,以便計算總字節數,代碼如下:

package com.jph.ufh.utils;

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.http.HttpEntity;
import org.apache.http.entity.HttpEntityWrapper;

/**
 * ProgressOutHttpEntity:輸出流(OutputStream)時記錄已發送字節數
 * @author JPH
 * Date:2014.11.03
 */
public class ProgressOutHttpEntity extends HttpEntityWrapper {
	/**進度監聽對象**/
    private final ProgressListener listener;
    public ProgressOutHttpEntity(final HttpEntity entity,final ProgressListener listener) {
        super(entity);
        this.listener = listener;
    }

    public static class CountingOutputStream extends FilterOutputStream {

        private final ProgressListener listener;
        private long transferred;

        CountingOutputStream(final OutputStream out,
                final ProgressListener listener) {
            super(out);
            this.listener = listener;
            this.transferred = 0;
        }

        @Override
        public void write(final byte[] b, final int off, final int len)
                throws IOException {
            out.write(b, off, len);
            this.transferred += len;
            this.listener.transferred(this.transferred);
        }

        @Override
        public void write(final int b) throws IOException {
            out.write(b);
            this.transferred++;
            this.listener.transferred(this.transferred);
        }

    }

    @Override
    public void writeTo(final OutputStream out) throws IOException {
        this.wrappedEntity.writeTo(out instanceof CountingOutputStream ? out
                : new CountingOutputStream(out, this.listener));
    }
    /**
     * 進度監聽器接口
     */
    public interface ProgressListener {
        public void transferred(long transferedBytes);
    }
}

最後就是使用上述實現的類和Httpclient進行上傳並顯示進度的功能,非常簡單,代碼如下,使用AsyncTask異步上傳。

/**
 * 異步AsyncTask+HttpClient上傳文件,支持多文件上傳,並顯示上傳進度
 * @author JPH
 * Date:2014.10.09
 * last modified 2014.11.03
 */
public class UploadUtilsAsync extends AsyncTask{
	/**服務器路徑**/
	private String url;
	/**上傳的參數**/
	private MapparamMap;
	/**要上傳的文件**/
	private ArrayListfiles;
	private long totalSize;
	private Context context;
	private ProgressDialog progressDialog;
	public UploadUtilsAsync(Context context,String url,MapparamMap,ArrayListfiles) {
		this.context=context;
		this.url=url;
		this.paramMap=paramMap;
		this.files=files;
	}

	@Override
	protected void onPreExecute() {//執行前的初始化
		// TODO Auto-generated method stub
		progressDialog=new ProgressDialog(context);
		progressDialog.setTitle("請稍等...");			
		progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		progressDialog.setCancelable(true);
		progressDialog.show();
		super.onPreExecute();
	}

	@Override
	protected String doInBackground(String... params) {//執行任務
		// TODO Auto-generated method stub
		MultipartEntityBuilder builder = MultipartEntityBuilder.create();
		builder.setCharset(Charset.forName(HTTP.UTF_8));//設置請求的編碼格式
		builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);//設置浏覽器兼容模式
		int count=0;
		for (File file:files) {
//			FileBody fileBody = new FileBody(file);//把文件轉換成流對象FileBody
//			builder.addPart("file"+count, fileBody);
			builder.addBinaryBody("file"+count, file);
			count++;
		}		
		builder.addTextBody("method", paramMap.get("method"));//設置請求參數
		builder.addTextBody("fileTypes", paramMap.get("fileTypes"));//設置請求參數
		HttpEntity entity = builder.build();// 生成 HTTP POST 實體  	
		totalSize = entity.getContentLength();//獲取上傳文件的大小
        ProgressOutHttpEntity progressHttpEntity = new ProgressOutHttpEntity(
        		entity, new ProgressListener() {
                    @Override
                    public void transferred(long transferedBytes) {
                        publishProgress((int) (100 * transferedBytes / totalSize));//更新進度
                    }
                });
        return uploadFile(url, progressHttpEntity);
	}

	@Override
	protected void onProgressUpdate(Integer... values) {//執行進度
		// TODO Auto-generated method stub
		Log.i("info", "values:"+values[0]);
		progressDialog.setProgress((int)values[0]);//更新進度條
		super.onProgressUpdate(values);
	}

	@Override
	protected void onPostExecute(String result) {//執行結果
		// TODO Auto-generated method stub
		Log.i("info", result);
		Toast.makeText(context, result, Toast.LENGTH_LONG).show();
		progressDialog.dismiss();
		super.onPostExecute(result);
	}
	/**
	 * 向服務器上傳文件
	 * @param url
	 * @param entity
	 * @return
	 */
	public String uploadFile(String url, ProgressOutHttpEntity entity) {				
		HttpClient httpClient=new DefaultHttpClient();// 開啟一個客戶端 HTTP 請求 
        httpClient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
        httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);// 設置連接超時時間
        HttpPost httpPost = new HttpPost(url);//創建 HTTP POST 請求  
        httpPost.setEntity(entity);
        try {
            HttpResponse httpResponse = httpClient.execute(httpPost);
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                return "文件上傳成功";
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ConnectTimeoutException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (httpClient != null && httpClient.getConnectionManager() != null) {
                httpClient.getConnectionManager().shutdown();
            }
        }
        return "文件上傳失敗";
    }
}

關於服務器端如何接收:可以參考:《Android網絡編程之使用HttpClient批量上傳文件》,我在裡面已經介紹的很清楚了。

如果你覺得這篇博文對你有幫助的話,請為這篇博文點個贊吧!也可以關注fengyuzhengfan的博客,收看更多精彩!http://blog.csdn.net/fengyuzhengfan/

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved