六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 1157|回复: 0

Android上传图片(PHP服务器)

[复制链接]
 楼主| 发表于 2015-6-1 12:02:31 | 显示全部楼层 |阅读模式
Android上传图片(PHP服务器)
原理
Android客户端模拟一个HTTP的Post请求到服务器端,服务器端接收相应的Post请求后,返回响应信息给给客户端。

PHP服务器
  1. <?php
  2.   move_uploaded_file($_FILES['file']['tmp_name'], "./upload/".$_FILES["file"]["name"]);
  3. ?>
复制代码
Android客户端
  1. package com.example.uploadfile.app;

  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.os.Environment;
  5. import android.os.StrictMode;
  6. import android.view.View;
  7. import android.widget.Button;
  8. import android.widget.TextView;
  9. import android.widget.Toast;

  10. import java.io.DataOutputStream;
  11. import java.io.FileInputStream;
  12. import java.io.InputStream;
  13. import java.net.HttpURLConnection;
  14. import java.net.URL;

  15. public class MainActivity extends Activity
  16. {
  17.     private String fileName = "image.jpg";  //报文中的文件名参数
  18.     private String path = Environment.getExternalStorageDirectory().getPath();  //Don't use "/sdcard/" here
  19.     private String uploadFile = path + "/" + fileName;    //待上传的文件路径
  20.     private String postUrl = "http://mycloudnote.sinaapp.com/upload.php"; //处理POST请求的页面
  21.     private TextView mText1;
  22.     private TextView mText2;
  23.     private Button mButton;

  24.     @Override
  25.     public void onCreate(Bundle savedInstanceState)
  26.     {
  27.         super.onCreate(savedInstanceState);
  28.         setContentView(R.layout.activity_main);
  29.         //"文件路径:\n"+
  30.         mText1 = (TextView) findViewById(R.id.myText1);
  31.         mText1.setText(uploadFile);
  32.         //"上传网址:\n"+
  33.         mText2 = (TextView) findViewById(R.id.myText2);
  34.         mText2.setText(postUrl);
  35.         /* 设置mButton的onClick事件处理 */
  36.         mButton = (Button) findViewById(R.id.myButton);
  37.         mButton.setOnClickListener(new View.OnClickListener()
  38.         {
  39.             public void onClick(View v)
  40.             {
  41.                 uploadFile();
  42.             }
  43.         });
  44.     }

  45.     /* 上传文件至Server的方法 */
  46.     private void uploadFile()
  47.     {
  48.         String end = "\r\n";
  49.         String twoHyphens = "--";
  50.         String boundary = "*****";
  51.         try
  52.         {
  53.             URL url = new URL(postUrl);
  54.             HttpURLConnection con = (HttpURLConnection) url.openConnection();
  55.           /* Output to the connection. Default is false,
  56.              set to true because post method must write something to the connection */
  57.             con.setDoOutput(true);
  58.           /* Read from the connection. Default is true.*/
  59.             con.setDoInput(true);
  60.           /* Post cannot use caches */
  61.             con.setUseCaches(false);
  62.           /* Set the post method. Default is GET*/
  63.             con.setRequestMethod("POST");
  64.           /* 设置请求属性 */
  65.             con.setRequestProperty("Connection", "Keep-Alive");
  66.             con.setRequestProperty("Charset", "UTF-8");
  67.             con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
  68.           /*设置StrictMode 否则HTTPURLConnection连接失败,因为这是在主进程中进行网络连接*/
  69.             StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
  70.           /* 设置DataOutputStream,getOutputStream中默认调用connect()*/
  71.             DataOutputStream ds = new DataOutputStream(con.getOutputStream());  //output to the connection
  72.             ds.writeBytes(twoHyphens + boundary + end);
  73.             ds.writeBytes("Content-Disposition: form-data; " +
  74.                     "name="file";filename="" +
  75.                     fileName + """ + end);
  76.             ds.writeBytes(end);
  77.           /* 取得文件的FileInputStream */
  78.             FileInputStream fStream = new FileInputStream(uploadFile);
  79.           /* 设置每次写入8192bytes */
  80.             int bufferSize = 8192;
  81.             byte[] buffer = new byte[bufferSize];   //8k
  82.             int length = -1;
  83.           /* 从文件读取数据至缓冲区 */
  84.             while ((length = fStream.read(buffer)) != -1)
  85.             {
  86.             /* 将资料写入DataOutputStream中 */
  87.                 ds.write(buffer, 0, length);
  88.             }
  89.             ds.writeBytes(end);
  90.             ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
  91.           /* 关闭流,写入的东西自动生成Http正文*/
  92.             fStream.close();
  93.           /* 关闭DataOutputStream */
  94.             ds.close();
  95.           /* 从返回的输入流读取响应信息 */
  96.             InputStream is = con.getInputStream();  //input from the connection 正式建立HTTP连接
  97.             int ch;
  98.             StringBuffer b = new StringBuffer();
  99.             while ((ch = is.read()) != -1)
  100.             {
  101.                 b.append((char) ch);
  102.             }
  103.           /* 显示网页响应内容 */
  104.             Toast.makeText(MainActivity.this, b.toString().trim(), Toast.LENGTH_SHORT).show();//Post成功
  105.         } catch (Exception e)
  106.         {
  107.             /* 显示异常信息 */
  108.             Toast.makeText(MainActivity.this, "Fail:" + e, Toast.LENGTH_SHORT).show();//Post失败
  109.         }
  110.     }
  111. }
  112. 复制代码
复制代码
设置连接(HTTP头) -> 建立TCP连接 -> 设置HTTP正文 -> 建立HTTP连接(正式Post)-> 从返回的输入流读取响应信息

1.设置连接(HTTP头)
  1. URL url = new URL(postUrl);
  2. HttpURLConnection con = (HttpURLConnection) url.openConnection();
  3. /* Output to the connection. Default is false,
  4. set to true because post method must write something to the connection */
  5. con.setDoOutput(true);
  6. /* Read from the connection. Default is true.*/
  7. con.setDoInput(true);
  8. /* Post cannot use caches */
  9. con.setUseCaches(false);
  10. /* Set the post method. Default is GET*/
  11. con.setRequestMethod("POST");
  12. /* 设置请求属性 */
  13. con.setRequestProperty("Connection", "Keep-Alive");
  14. con.setRequestProperty("Charset", "UTF-8");
  15. con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
  16. 复制代码
复制代码
2.建立TCP连接
  1. DataOutputStream ds = new DataOutputStream(con.getOutputStream());  //output to the connection
复制代码
con.getOutputStream()中会默认调用con.connect(),此时客户端与服务器建立的只是1个TCP连接而非HTTP。
HTTP请求=HTTP头+HTTP正文。
在connect()里面,会根据HttpURLConnection对象的配置值生成HTTP头,所以对con的一切配置都必须在connect()方法之前完成。

3.设置HTTP正文
正文通过DataOutputStream写入,只是写入内存而不会发送到网络中去,而是在流关闭时,根据写入的内容生成HTTP正文。
  1. ds.writeBytes(twoHyphens + boundary + end);
  2. ds.writeBytes("Content-Disposition: form-data; " +
  3.     "name="file";filename="" +
  4.     fileName + """ + end);
  5. ds.writeBytes(end);
  6. /* 取得文件的FileInputStream */
  7. FileInputStream fStream = new FileInputStream(uploadFile);
  8. /* 设置每次写入8192bytes */
  9. int bufferSize = 8192;
  10. byte[] buffer = new byte[bufferSize];   //8k
  11. int length = -1;
  12. /* 从文件读取数据至缓冲区 */
  13. while ((length = fStream.read(buffer)) != -1)
  14. {
  15.   /* 将资料写入DataOutputStream中 */
  16.   ds.write(buffer, 0, length);
  17. }
  18. ds.writeBytes(end);
  19. ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
  20. /* 关闭流,写入的东西自动生成Http正文*/
  21. fStream.close();
  22. /* 关闭DataOutputStream */
  23. ds.close();
复制代码
4.建立HTTP连接(正式Post)
至此,HTTP请求设置完毕,con.getInputStream()中会将请求(HTTP头+HTTP正文)发送到服务器,并返回一个输入流。所以在getInputStream()之前,HTTP正文部分一定要先设置好。
  1. InputStream is = con.getInputStream();  //input from the connection 正式建立HTTP连接
复制代码
5.从返回的输入流读取响应信息
  1. int ch;
  2. StringBuffer b = new StringBuffer();
  3. while ((ch = is.read()) != -1)
  4. {
  5.   b.append((char) ch);
  6. }
  7. /* 显示网页响应内容 */
  8. Toast.makeText(MainActivity.this, b.toString().trim(), Toast.LENGTH_SHORT).show();//Post成功
  9. 复制代码
复制代码
布局XML
两个Text和一个Button
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     tools:context="${packageName}.${activityClass}">

  6.     <TextView
  7.         android:layout_width="wrap_content"
  8.         android:layout_height="wrap_content"
  9.         android:text="New Text"
  10.         android:id="@+id/myText1"
  11.         android:layout_above="@+id/myText2"
  12.         android:layout_centerHorizontal="true"
  13.         android:layout_marginBottom="80dp"/>

  14.     <TextView
  15.         android:layout_width="wrap_content"
  16.         android:layout_height="wrap_content"
  17.         android:text="New Text"
  18.         android:id="@+id/myText2"
  19.         android:layout_centerVertical="true"
  20.         android:layout_centerHorizontal="true"/>

  21.     <Button
  22.         android:layout_width="wrap_content"
  23.         android:layout_height="wrap_content"
  24.         android:text="Upload"
  25.         android:id="@+id/myButton"
  26.         android:layout_marginTop="80dp"
  27.         android:layout_below="@+id/myText2"
  28.         android:layout_centerHorizontal="true"/>
  29. </RelativeLayout>
复制代码
AndroidManifest
添加网络权限、SD卡读写权限、挂载文件系统权限。
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3.     package="com.example.uploadfile.app" >

  4.     <application
  5.         android:allowBackup="true"
  6.         android:icon="@drawable/ic_launcher"
  7.         android:label="@string/app_name"
  8.         android:theme="@style/AppTheme" >
  9.         <activity
  10.             android:name="com.example.uploadfile.app.MainActivity"
  11.             android:label="@string/app_name" >
  12.             <intent-filter>
  13.                 <action android:name="android.intent.action.MAIN" />

  14.                 <category android:name="android.intent.category.LAUNCHER" />
  15.             </intent-filter>
  16.         </activity>
  17.     </application>
  18.     <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="15" />
  19.     <uses-permission android:name="android.permission.INTERNET" />
  20.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  21.     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
  22. </manifest>
复制代码
注意事项
1.由于Android不建议在主进程中进行网络访问,所以使用HttpURLConnection连接到服务端时抛出异常,加入以下语句即可。
  1. StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
复制代码
2.获取SD卡路径时,请使用Environment.getExternalStorageDirectory().getPath();而不是"/sdcard/"

参考文章Android上传图片(PHP服务器)
摘自:http://www.cnblogs.com/chenyg32/p/3822639.html

该会员没有填写今日想说内容.
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表