Android文件上传,PHP端接收

来源:互联网 发布:网络教学与传统教学 编辑:程序博客网 时间:2024/04/30 10:16

   最近项目中要用优化文件上传操作,因此对Android端文件上传做下总结。测试服务器端就用PHP写了,比较简单,代码如下:

[php] view plaincopy
  1. <?php  
  2. $base_path = "./uploads/"//接收文件目录  
  3. $target_path = $base_path . basename ( $_FILES ['uploadfile'] ['name'] );  
  4. if (move_uploaded_file ( $_FILES ['uploadfile'] ['tmp_name'], $target_path )) {  
  5.     $array = array ("code" => "1""message" => $_FILES ['uploadfile'] ['name'] );  
  6.     echo json_encode ( $array );  
  7. else {  
  8.     $array = array ("code" => "0""message" => "There was an error uploading the file, please try again!" . $_FILES ['uploadfile'] ['error'] );  
  9.     echo json_encode ( $array );  
  10. }  
  11. ?>  

     我主要写了三种上传:人造POST请求、httpclient4(需要httpmime-4.1.3.jar)、AsyncHttpClient(对appache的HttpClient进行了进一步封装,了解更多...),当然为了并列起来看比较方便,前两种上传我直接写在主线程了,不知道对速度测试有没有影响,老鸟看到请给予批评指正,嘿嘿,下面上代码:

[java] view plaincopy
  1. package com.example.fileupload;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.DataOutputStream;  
  5. import java.io.File;  
  6. import java.io.FileInputStream;  
  7. import java.io.FileNotFoundException;  
  8. import java.io.IOException;  
  9. import java.io.InputStream;  
  10. import java.io.InputStreamReader;  
  11. import java.net.HttpURLConnection;  
  12. import java.net.URL;  
  13.   
  14. import org.apache.http.HttpEntity;  
  15. import org.apache.http.HttpResponse;  
  16. import org.apache.http.HttpVersion;  
  17. import org.apache.http.client.ClientProtocolException;  
  18. import org.apache.http.client.HttpClient;  
  19. import org.apache.http.client.methods.HttpPost;  
  20. import org.apache.http.entity.mime.MultipartEntity;  
  21. import org.apache.http.entity.mime.content.FileBody;  
  22. import org.apache.http.impl.client.DefaultHttpClient;  
  23. import org.apache.http.params.CoreProtocolPNames;  
  24. import org.apache.http.util.EntityUtils;  
  25.   
  26. import android.app.Activity;  
  27. import android.os.Bundle;  
  28. import android.util.Log;  
  29. import android.view.View;  
  30. import android.view.View.OnClickListener;  
  31. import android.widget.Button;  
  32.   
  33. import com.loopj.android.http.AsyncHttpClient;  
  34. import com.loopj.android.http.AsyncHttpResponseHandler;  
  35. import com.loopj.android.http.RequestParams;  
  36.   
  37. /** 
  38.  *  
  39.  * ClassName:UploadActivity Function: TODO 测试上传文件,PHP服务器端接收 Reason: TODO ADD 
  40.  * REASON 
  41.  *  
  42.  * @author Jerome Song 
  43.  * @version 
  44.  * @since Ver 1.1 
  45.  * @Date 2013 2013-4-20 上午8:53:44 
  46.  *  
  47.  * @see 
  48.  */  
  49. public class UploadActivity extends Activity implements OnClickListener {  
  50.     private final String TAG = "UploadActivity";  
  51.   
  52.     private static final String path = "/mnt/sdcard/Desert.jpg";  
  53.     private String uploadUrl = "http://192.168.1.102:8080/Android/testupload.php";  
  54.     private Button btnAsync, btnHttpClient, btnCommonPost;  
  55.     private AsyncHttpClient client;  
  56.   
  57.     @Override  
  58.     protected void onCreate(Bundle savedInstanceState) {  
  59.         super.onCreate(savedInstanceState);  
  60.         setContentView(R.layout.activity_upload);  
  61.         initView();  
  62.         client = new AsyncHttpClient();  
  63.     }  
  64.   
  65.     private void initView() {  
  66.         btnCommonPost = (Button) findViewById(R.id.button1);  
  67.         btnHttpClient = (Button) findViewById(R.id.button2);  
  68.         btnAsync = (Button) findViewById(R.id.button3);  
  69.         btnCommonPost.setOnClickListener(this);  
  70.         btnHttpClient.setOnClickListener(this);  
  71.         btnAsync.setOnClickListener(this);  
  72.     }  
  73.   
  74.     @Override  
  75.     public void onClick(View v) {  
  76.         long startTime = System.currentTimeMillis();  
  77.         String tag = null;  
  78.         try {  
  79.             switch (v.getId()) {  
  80.             case R.id.button1:  
  81.                 upLoadByCommonPost();  
  82.                 tag = "CommonPost====>";  
  83.                 break;  
  84.             case R.id.button2:  
  85.                 upLoadByHttpClient4();  
  86.                 tag = "HttpClient====>";  
  87.                 break;  
  88.             case R.id.button3:  
  89.                 upLoadByAsyncHttpClient();  
  90.                 tag = "AsyncHttpClient====>";  
  91.                 break;  
  92.             default:  
  93.                 break;  
  94.             }  
  95.         } catch (Exception e) {  
  96.             e.printStackTrace();  
  97.   
  98.         }  
  99.         Log.i(TAG, tag + "wasteTime = "  
  100.                 + (System.currentTimeMillis() - startTime));  
  101.     }  
  102.   
  103.     /** 
  104.      * upLoadByAsyncHttpClient:由人造post上传 
  105.      *  
  106.      * @return void 
  107.      * @throws IOException 
  108.      * @throws 
  109.      * @since CodingExample Ver 1.1 
  110.      */  
  111.     private void upLoadByCommonPost() throws IOException {  
  112.         String end = "\r\n";  
  113.         String twoHyphens = "--";  
  114.         String boundary = "******";  
  115.         URL url = new URL(uploadUrl);  
  116.         HttpURLConnection httpURLConnection = (HttpURLConnection) url  
  117.                 .openConnection();  
  118.         httpURLConnection.setChunkedStreamingMode(128 * 1024);// 128K  
  119.         // 允许输入输出流  
  120.         httpURLConnection.setDoInput(true);  
  121.         httpURLConnection.setDoOutput(true);  
  122.         httpURLConnection.setUseCaches(false);  
  123.         // 使用POST方法  
  124.         httpURLConnection.setRequestMethod("POST");  
  125.         httpURLConnection.setRequestProperty("Connection""Keep-Alive");  
  126.         httpURLConnection.setRequestProperty("Charset""UTF-8");  
  127.         httpURLConnection.setRequestProperty("Content-Type",  
  128.                 "multipart/form-data;boundary=" + boundary);  
  129.   
  130.         DataOutputStream dos = new DataOutputStream(  
  131.                 httpURLConnection.getOutputStream());  
  132.         dos.writeBytes(twoHyphens + boundary + end);  
  133.         dos.writeBytes("Content-Disposition: form-data; name=\"uploadfile\"; filename=\""  
  134.                 + path.substring(path.lastIndexOf("/") + 1) + "\"" + end);  
  135.         dos.writeBytes(end);  
  136.   
  137.         FileInputStream fis = new FileInputStream(path);  
  138.         byte[] buffer = new byte[8192]; // 8k  
  139.         int count = 0;  
  140.         // 读取文件  
  141.         while ((count = fis.read(buffer)) != -1) {  
  142.             dos.write(buffer, 0, count);  
  143.         }  
  144.         fis.close();  
  145.         dos.writeBytes(end);  
  146.         dos.writeBytes(twoHyphens + boundary + twoHyphens + end);  
  147.         dos.flush();  
  148.         InputStream is = httpURLConnection.getInputStream();  
  149.         InputStreamReader isr = new InputStreamReader(is, "utf-8");  
  150.         BufferedReader br = new BufferedReader(isr);  
  151.         String result = br.readLine();  
  152.         Log.i(TAG, result);  
  153.         dos.close();  
  154.         is.close();  
  155.     }  
  156.   
  157.     /** 
  158.      * upLoadByAsyncHttpClient:由HttpClient4上传 
  159.      *  
  160.      * @return void 
  161.      * @throws IOException 
  162.      * @throws ClientProtocolException 
  163.      * @throws 
  164.      * @since CodingExample Ver 1.1 
  165.      */  
  166.     private void upLoadByHttpClient4() throws ClientProtocolException,  
  167.             IOException {  
  168.         HttpClient httpclient = new DefaultHttpClient();  
  169.         httpclient.getParams().setParameter(  
  170.                 CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);  
  171.         HttpPost httppost = new HttpPost(uploadUrl);  
  172.         File file = new File(path);  
  173.         MultipartEntity entity = new MultipartEntity();  
  174.         FileBody fileBody = new FileBody(file);  
  175.         entity.addPart("uploadfile", fileBody);  
  176.         httppost.setEntity(entity);  
  177.         HttpResponse response = httpclient.execute(httppost);  
  178.         HttpEntity resEntity = response.getEntity();  
  179.         if (resEntity != null) {  
  180.             Log.i(TAG, EntityUtils.toString(resEntity));  
  181.         }  
  182.         if (resEntity != null) {  
  183.             resEntity.consumeContent();  
  184.         }  
  185.         httpclient.getConnectionManager().shutdown();  
  186.     }  
  187.   
  188.     /** 
  189.      * upLoadByAsyncHttpClient:由AsyncHttpClient框架上传 
  190.      *  
  191.      * @return void 
  192.      * @throws FileNotFoundException 
  193.      * @throws 
  194.      * @since CodingExample Ver 1.1 
  195.      */  
  196.     private void upLoadByAsyncHttpClient() throws FileNotFoundException {  
  197.         RequestParams params = new RequestParams();  
  198.         params.put("uploadfile"new File(path));  
  199.         client.post(uploadUrl, params, new AsyncHttpResponseHandler() {  
  200.             @Override  
  201.             public void onSuccess(int arg0, String arg1) {  
  202.                 super.onSuccess(arg0, arg1);  
  203.                 Log.i(TAG, arg1);  
  204.             }  
  205.         });  
  206.     }  
  207.   
  208. }  


    Andriod被我们熟知的上传就是由appache提供给的httpclient4了,毕竟比较简单,腾讯微博什么的sdk也都是这么做的,大家可以参考:

[java] view plaincopy
  1. /** 
  2.      * Post方法传送文件和消息 
  3.      *  
  4.      * @param url  连接的URL 
  5.      * @param queryString 请求参数串 
  6.      * @param files 上传的文件列表 
  7.      * @return 服务器返回的信息 
  8.      * @throws Exception 
  9.      */  
  10.     public String httpPostWithFile(String url, String queryString, List<NameValuePair> files) throws Exception {  
  11.   
  12.         String responseData = null;  
  13.   
  14.         URI tmpUri=new URI(url);  
  15.         URI uri = URIUtils.createURI(tmpUri.getScheme(), tmpUri.getHost(), tmpUri.getPort(), tmpUri.getPath(),   
  16.                 queryString, null);  
  17.         Log.i(TAG, "QHttpClient httpPostWithFile [1]  uri = "+uri.toURL());  
  18.           
  19.           
  20.         MultipartEntity mpEntity = new MultipartEntity();  
  21.         HttpPost httpPost = new HttpPost(uri);  
  22.         StringBody stringBody;  
  23.         FileBody fileBody;  
  24.         File targetFile;  
  25.         String filePath;  
  26.         FormBodyPart fbp;  
  27.           
  28.         List<NameValuePair> queryParamList=QStrOperate.getQueryParamsList(queryString);  
  29.         for(NameValuePair queryParam:queryParamList){  
  30.             stringBody=new StringBody(queryParam.getValue(),Charset.forName("UTF-8"));  
  31.             fbp= new FormBodyPart(queryParam.getName(), stringBody);  
  32.             mpEntity.addPart(fbp);  
  33. //            Log.i(TAG, "------- "+queryParam.getName()+" = "+queryParam.getValue());  
  34.         }  
  35.           
  36.         for (NameValuePair param : files) {  
  37.             filePath = param.getValue();  
  38.             targetFile= new File(filePath);  
  39.             fileBody = new FileBody(targetFile,"application/octet-stream");  
  40.             fbp= new FormBodyPart(param.getName(), fileBody);  
  41.             mpEntity.addPart(fbp);  
  42.               
  43.         }  
  44.   
  45. //        Log.i(TAG, "---------- Entity Content Type = "+mpEntity.getContentType());  
  46.   
  47.         httpPost.setEntity(mpEntity);  
  48.           
  49.         try {  
  50.             HttpResponse response=httpClient.execute(httpPost);  
  51.             Log.i(TAG, "QHttpClient httpPostWithFile [2] StatusLine = "+response.getStatusLine());  
  52.             responseData =EntityUtils.toString(response.getEntity());  
  53.         } catch (Exception e) {  
  54.             e.printStackTrace();  
  55.         }finally{  
  56.           httpPost.abort();  
  57.         }  
  58.         Log.i(TAG, "QHttpClient httpPostWithFile [3] responseData = "+responseData);  
  59.         return responseData;  
  60.     }  


    很明显,开源框架的写法最简单有效,而且为异步的,提供出Handler进行结果返回,普通人造post代码量最大,上传速度大家也可以测一下,我附一张图,我上传的图片850kb左右

    总体看来,代码量最多的写法可能上传速度好点儿,asyncHttpClient的上传方式速度也很理想,主要是用起来简单。

   有时可能还会有上传进度返回的需求,第一种流的读写方式应该很简单解决,后两种可能还得下点儿功夫研究研究,有兴趣的朋友可以一块儿交流研究。