2012年9月24日 星期一

Android 開發筆記 - HTTP Post (File Uploading) Progress Report

之前研究 HTTP Post 的方法時,順手實作了支援 Cookie 等功能,久了之後就會想到如何監控上傳進度的部分,原理都很簡單,但要熟整各個 framework 才能方便進行。所幸網路上好心人士非常多,找到這篇 Android Multipart POST with Progress Bar 真的超佛心的,就順手修改一下一點架構。


實作概念:


繼承 org.apache.http.entity.mime.MultipartEntity 物件後,當寫出資料時,記錄已累積的寫出量,在搭配總共要送出的資料量,簡易的除法就能得知目前所進行的進度了。


我自己的粗略使用:


@ HttpPostMultipartEntity.java:


// 九成九一樣,單純改一些變數名稱
// src: http://toolongdidntread.com/android/android-multipart-post-with-progress-bar/
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;


import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;


public class HttpPostMultipartEntity extends MultipartEntity {
       private final HttpPostProgressHandler handler;
       public HttpPostMultipartEntity(final HttpPostProgressHandler handler) {
              super();
              this.handler = handler;
       }
       public HttpPostMultipartEntity(final HttpMultipartMode mode, final HttpPostProgressHandler handler) {
              super(mode);
              this.handler = handler;
       }
       public HttpPostMultipartEntity(final HttpMultipartMode mode, final String boundary, final Charset charset, final HttpPostProgressHandler handler) {
              super(mode,boundary,charset);
              this.handler = handler;
       }

       @Override
       public void writeTo(final OutputStream outstream) throws IOException {
              super.writeTo(new HttpPostOutputStream(outstream, this.handler));
       }

       public static class HttpPostOutputStream extends FilterOutputStream {
              private final HttpPostProgressHandler handler;
              private long transferred;

              public HttpPostOutputStream(final OutputStream out, final HttpPostProgressHandler handler) {
                     super(out);
                     this.handler = handler;
                     this.transferred = 0;
              }

              public void write(byte[] b, int off, int len) throws IOException {
                     out.write(b, off, len);
                     this.transferred += len;
                     if( this.handler != null )
                             this.handler.postStatusReport(this.transferred);

              }

              public void write(int b) throws IOException {
                     out.write(b);
                     this.transferred ++;
                     if( this.handler != null )

                            this.handler.postStatusReport(this.transferred);
              }
       }
}


@ HttpPostProgressHandler.java:


public interface HttpPostProgressHandler {
       void setPostDataSize(long size);
       void postStatusReport(long transferred);
}


HTTP POST Usage:


void doPost( String api_url, String file_path, HttpPostProgressHandler reporter ) {
       List<NameValuePair> mParams = new ArrayList<NameValuePair>();
       mParams.add( new BasicNameValuePair( "path", remote_path ) );
       mParams.add( new BasicNameValuePair( "mode", "upload_file") );
       mParams.add( new BasicNameValuePair( "name", filename) );
       mParams.add( new BasicNameValuePair( "code", edit_code ) );


       // multipart with args
       //MultipartEntity entity=new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
       HttpPostMultipartEntity entity = new HttpPostMultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, reporter);
       for( NameValuePair mItem : mParams )
              try {
                     entity.addPart(item.getName(),new StringBody(mItem.getValue(), Charset.forName("UTF-8")));
              } catch (UnsupportedEncodingException e) {
                     e.printStackTrace();
              }

       File mFile = new File(file_path);
       if( ! mFile.exists() ) {
              System.out.println("File not found:"+local_path);
              return;
       }

       // add cookie
       CookieStore mCookieStore = BasicCookieStore()
       Cookie x = new BasicClientCookie("MyCookie", "MyCookieValue");
       ((BasicClientCookie)x).setPath("/");
       ((BasicClientCookie)x).setDomain("ServerDomain");
       cookieStore.addCookie( x );


       // add file
       entity.addPart( "file", new FileBody( mFile ) );


       // upload api
       HttpPost mHttpPost = new HttpPost(api_url);
       mHttpPost.setEntity(entity);


       // set post data total size
       if( reporter != null )
              reporter.setPostDataSize(entity.getContentLength());


       // use cookie
       HttpClient mHttpClient = new DefaultHttpClient();
       HttpContext mHttpContext = new BasicHttpContext();
       mHttpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

       try {
              HttpResponse response = mHttpClient.execute( mHttpPost, mHttpContext );
              HttpEntity result = response.getEntity();
              System.out.println( "Result:" + EntityUtils.toString(result) );
       } catch (Exception e) {
              e.printStackTrace();
       }
}


Main:


new Thread( new Runnable() {
       @Override
       public void run() {
              doPost(
                     "http://mytest/api/upload.php" ,
                     "/mnt/sdcard/test.png",
                     new HttpPostProgressHandler() {
                            long total_size = 0;


                            @Override
                            public void setPostDataSize(long size) {
                                   total_size = size;
                            }


                            @Override
                            public void postStatusReport(long transferred) {
                                   if(total_size == 0)
                                          return;
                                   System.out.println("Status:"+(float)transferred/total_size);
                            }
                     }
              );
       }
} ).start();


Others:


import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;


import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;


public class HttpQueryUsage {
       public static HttpPost createHttpPost(String url, List<NameValuePair> params, List<NameValuePair> files, HttpPostProgressHandler handler) {
              if( url == null )
                     return null;


              MultipartEntity entity=new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
              if( params != null && params.size() > 0)
                     for( NameValuePair item : params )
                            try {
                                   entity.addPart(item.getName(),new StringBody(item.getValue(), Charset.forName("UTF-8")));
                            } catch (UnsupportedEncodingException e) {
                                   e.printStackTrace();
                            }


              if( files != null && files.size() > 0 )
                     for( NameValuePair file : files ) {
                            try {
                                   File src = new File(file.getValue());
                                   if(!src.exists())
                                          continue;
                                   entity.addPart( file.getName(), new FileBody( src ) );
                            } catch (Exception e) {
                                   e.printStackTrace();
                            }
                     }

              HttpPost post = new HttpPost(url);
              post.setEntity(entity);


              if(handler!=null)
                     handler.setPostDataSize(entity.getContentLength());

              return post;
       }
       public static HttpGet createHttpGet(String url, List<NameValuePair> params) {
              if( url != null )
                     return new HttpGet( params == null || params.size() == 0 ? url : url + "?" + URLEncodedUtils.format(params, "utf-8") );
              return null;
       }
       public static HttpResponse executeQuery(HttpUriRequest request, CookieStore cookie_store) throws ClientProtocolException, IOException {
              HttpClient mClient = new DefaultHttpClient();
              if( cookie_store == null )
                     return mClient.execute(request);
              HttpContext mHttpContext = new BasicHttpContext();
              mHttpContext.setAttribute(ClientContext.COOKIE_STORE, cookie_store);
              return mClient.execute(request, mHttpContext);
       }
       public static void exampleGetUsage() {
              String url = "http://localhost/login.php";
              List<NameValuePair> params = new ArrayList<NameValuePair>();
              params.add( new BasicNameValuePair("user","username") );
              params.add( new BasicNameValuePair("passwd","password") );
              try {
                     CookieStore cookie_store = new BasicCookieStore();
                     HttpEntity result = HttpQueryUsage.executeQuery(HttpQueryUsage.createHttpGet(url, params), cookie_store).getEntity();
                     for( Cookie item : cookie_store.getCookies() )
                            System.out.println("CookieName: "+item.getName()+",CookieValue: "+item.getValue() );
                     if( result != null )
                            System.out.println("PageResult:"+EntityUtils.toString(result));
              } catch (Exception e) {
                     e.printStackTrace();
              }
       }
       public static void examplePostUsage() {
              String url = "http://localhost/login.php";
              List<NameValuePair> params = new ArrayList<NameValuePair>();
              params.add( new BasicNameValuePair("user","username") );
              params.add( new BasicNameValuePair("passwd","password") );
              try {
                     CookieStore cookie_store = new BasicCookieStore();
                     HttpEntity result = HttpQueryUsage.executeQuery(HttpQueryUsage.createHttpPost(url, params, null, null), cookie_store).getEntity();
                     for( Cookie item : cookie_store.getCookies() )
                            System.out.println("CookieName: "+item.getName()+",CookieValue: "+item.getValue() );
                     if( result != null )
                            System.out.println("PageResult:"+EntityUtils.toString(result));
              } catch (Exception e) {
                     e.printStackTrace();
              }
       }
       public static void examplePostFileUploadingUsage() {
              String url = "http://localhost/login.php";
              List<NameValuePair> files = new ArrayList<NameValuePair>();
              files.add( new BasicNameValuePair("file1","/mnt/sdcard/test.png") );
              try {
                     CookieStore cookie_store = new BasicCookieStore();
                     HttpEntity result = HttpQueryUsage.executeQuery(HttpQueryUsage.createHttpPost(url, null, files, null), cookie_store).getEntity();
                     for( Cookie item : cookie_store.getCookies() )
                            System.out.println("CookieName: "+item.getName()+",CookieValue: "+item.getValue() );
                     if( result != null )
                            System.out.println("PageResult:"+EntityUtils.toString(result));
              } catch (Exception e) {
                     e.printStackTrace();
              }
       }
}


沒有留言:

張貼留言