2011-12-19

在 Android 裡使用 HttpPost 讀取網頁與上傳檔案

使用 HttpPost 讀取網頁與 HttpGet 大同小異,比較不一樣的地方在於使用 HttpPost 上傳檔案時,需要使用三個外部的 Jar 檔:commons-io、httpmime 與 mime4j。


SingleHttpClient
public class SingleHttpClient {

    private static final String TAG = "SingleHttpClient";
    private static HttpClient httpClient;

    private SingleHttpClient() {
        // singleton
    }

    public static synchronized HttpClient get() {
        if (httpClient == null) {
            Log.i(TAG, "建立 Singleton HttpClient...");
            HttpParams params = new BasicHttpParams();
            // 取得 connection
            ConnManagerParams.setTimeout(params, 1000);
            // request timeout
            HttpConnectionParams.setConnectionTimeout(params, 5000);
            // response timeout
            HttpConnectionParams.setSoTimeout(params, 10000);
            SchemeRegistry schreg = new SchemeRegistry();
            schreg.register(new Scheme("http",
                    PlainSocketFactory.getSocketFactory(), 80));
            schreg.register(new Scheme("https",
                    SSLSocketFactory.getSocketFactory(), 443));
            // 因為 HttpClient 是 Singleton,所以使用特別的 ConnectionManager
            ClientConnectionManager ccMgr = new ThreadSafeClientConnManager(
                    params, schreg);
            httpClient = new DefaultHttpClient(ccMgr, params);
        }
        return httpClient;
    }
}
SingleHttpClient 與 HttpGet 裡的作法一樣,與 HttpGet 不一樣的是,為了重複使用「重試機制」,將重試機制從 Activity 裡抽出來成為 RetryHttp。

RetryHttp
public abstract class RetryHttp {

    private static final String TAG = "RetryHttp";
    private int retry = 3;

    public String doGet() throws IOException {
        throw new UnsupportedOperationException("必須實做 doGet() ");
    };

    public String doPost() throws IOException {
        throw new UnsupportedOperationException("必須實做 doPost() ");
    };

    /**
     * 實做重試機制
     * @return
     * @throws Exception
     */
    public String load(boolean post) throws Exception {
        int current = 0;
        while (current < this.retry) {
            current++;
            try {
                if (post) {
                    return this.doPost();
                }
                return this.doGet();
            }
            catch (IOException e) {
                Log.e(TAG, current + ".網路發生錯誤 - " + e.getMessage());
                if (current >= this.retry) {
                    Log.e(TAG, "重試失敗");
                    throw e;
                }
            }
            catch (Exception e) {
                Log.e(TAG, current + ".發生未知的錯誤 - " + e.getMessage());
                if (current >= this.retry) {
                    Log.e(TAG, "重試失敗");
                    throw e;
                }
            }
        }
        return null;
    }
}
任何需要「重試機制」的 HttpGet 或者 HttpPost,只要繼承 RetryHttp,並實做對應的 doGet() 或者 doPost() 即可。

HttpPostActivity
public class HttpPostActivity extends Activity {

    private static final String TAG = "HttpPostActivity";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        try {
            new PostHttp().load(true);
        }
        catch (Exception e) {
            Log.e(TAG, "不幸的事發生了");
        }
    }

    class PostHttp extends RetryHttp {

        @Override
        public String doPost() throws IOException {
            HttpClient client = SingleHttpClient.get();
            // http://244.putao.com.tw/putao/listChatReply.do?post.id=39369
            HttpPost request = new HttpPost(
                    "http://244.putao.com.tw/putao/listChatReply.do");

            // 一般的 Post
            // request.setEntity(this.createNormalEntity());

            // 帶檔的 Multipart Post
            request.setEntity(this.creteaMultipartEntity());

            String responseText = client.execute(request,
                    new BasicResponseHandler());
            responseText = responseText.replace("\n", "");
            responseText = responseText.replace("\r", "");
            responseText = responseText.replace(" ", "");
            int idx = responseText.indexOf("林口好吃的傳統燒餅@勝興碳烤缸爐餅");
            Log.d(TAG,
                    "取得 HTML(" + responseText.length() + ") - "
                            + TextUtils.substring(responseText, idx, idx + 10)
                            + " ... ");
            return responseText;
        }

        private MultipartEntity creteaMultipartEntity() throws IOException,
                UnsupportedEncodingException {
            InputStream is = getAssets().open("post.txt");
            byte[] data = IOUtils.toByteArray(is);
            InputStreamBody body = new InputStreamBody(
                    new ByteArrayInputStream(data), "file");
            MultipartEntity entity = new MultipartEntity();
            entity.addPart("file", body);
            entity.addPart("post.id", new StringBody("39369"));
            return entity;
        }

        private UrlEncodedFormEntity createNormalEntity()
                throws UnsupportedEncodingException {
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("post.id", "39369"));
            return new UrlEncodedFormEntity(params);
        }
    }
}
相關文章

1 則留言:

  1. 大大請問有原始碼可以提供嘛 麻煩你了 謝謝~

    回覆刪除