利用HTTP协议实现Android文件上传至WEB服务器,采用PHP接收文件(参考网上自己实现)

最近在做Android手机端的上传和下载功能。     上传文件的时候遇到了很大的麻烦,因为开始对网络编程这块十分不熟悉,加上对WEB服务器端也是一点不懂,搞了快一个星期才勉强实现,下面记录一下自己的过程:其中参考了网络编程的书籍,我本来是要对一个受保护的服务器进行上传文件,即需要输入帐号密码才可以成功上传文件,基于基础差,先做一个不用账户密码的,接下来再去实现可以访问受保护的服务器的功能。

1、首先搭建服务器端,朋友推荐我用了一款phpstudy集成的服务器环境搭建工具,确实非常好用。不用懂太多的PHP端,首先在phpstudy目录下的WWW目录下创建一个HTML文件,简单的写一个可以实现上传功能的界面,即一个选择文件框,还有一个上传的文件按钮,具体代码如下:





无标题文档





添加的代码就是图上标记为红色的部分,在里边添加。说明一下,这个
标签用于为用户输入创建HTML表单。

标签在被浏览器解析后会产生一个文本框和一个“浏览”按钮。单击浏览会弹出系统的文件选择框:如下图:


HTML中的form标签属性如下图:


图片来源与书上。

代码中的action=“upload_file.php”表示文件提交的时候会执行upload_file.php中的代码,这个文件主要实现对上传文件进行检查、复制等处理,代码如下:

创建一个PHP文件,也放在WWW目录下:





无标题文档



0)           //上传文件的错误代码,如果返回了错位代码可以对照错误信息进行修正
	{
		echo "Return Code:".$_FILES["file1"]["error"]."
"; } else { echo "Upload: ".$_FILES["file1"]["name"]."
"; //显示文件的名字,类型,大小,临时存放文件的路径 echo "Type: ".$_FILES["file1"]["type"]."
"; echo "Size: ".($_FILES["file1"]["size"]/1024)."kb
"; echo "Temp file1:".$_FILES["file1"]["tmp_name"]."
"; if(file_exists("./upload/".$_FILES["file1"]["name"])) //检测文件是否存在于upload目录下(这个目录是用来存放上传文件的目录,也是建立 在WWW目录下的),如果存在则返回提示。 { echo $_FILES["file1"]["name"]."already existst!"; } else {
//调用了一个PHP函数move_uploaded_file,把临时文件存放到我们制定的目录,并且改成我们上传时候的文件的名字。
move_uploaded_file($_FILES["file1"]["tmp_name"],"upload/".$_FILES["file1"]["name"]);
echo "Strore in:"."upload/".$_FILES["file1"]["name"]; //}}}else {echo "Invalid file1"; //文件超过20000字节则提示出错。}?>

 还是红色代码为写的PHP代码。这个代码主要采用 
  $_FILES这个全局变量,这个 全局变量会获取上传文件的消息,并用此变量来进行操作,例如检查文件大小、位置、是否存在等。具体解释见以上代码。 
  

至此我们的服务端的环境搭好了就,我们可以运行一下(首先在WWW目录下建立一个upload文件夹 这个也是跟上边的PHP里边的upload路径对应)。http://localhost/up.html  这个时候就会弹出选择文件上传的提示框,然后选文件上传就之后提示成功,就可以在WWW下的upload里查看上传文件,因为在php.ini配置文件中对上传文件大小做了控制,想要上传大文件的话可以在php.ini里边设置2个属性的大小:post_max_size          upload_max_filesize

把这两个属性设置好就可以了。

接下来就是安卓端代码的编写,这个代码也困扰了我好久,因为是看书上的例子,总也不能上传成功,后来发现是书上的列子传递参数好像传递错了,我改了一下就可以了。

代码如下:

首先是负责上传的工具类 httppost.java

package com.example.uploadfile;

import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.util.Log;

public class httppost {
	
	public static String post(String actionurl,String FileName) throws IOException  // 静态方法,直接在另外的类里可以调用
	{
		String BOUNDARY = java.util.UUID.randomUUID().toString();   //调用一个函数随机生成一个字符串作为分割线
		String PREFIX = "--",LINEND = "\r\n";
		String MULTIPART_FORM_DATA = "multipart/form-data";   //表单数据常量化
		String CHARSET = "UTF-8";  				//字符编码
		
		URL url = new URL(actionurl);                              
		HttpURLConnection conn = (HttpURLConnection)url.openConnection();//建立HTTP连接
		conn.setReadTimeout(5*1000);   	//设置从主机读取数据超时时间 单位:毫秒
		conn.setDoInput(true);		//设置允许输入
		conn.setDoOutput(true);		//设置允许输出
		conn.setUseCaches(false);	//设置不使用缓存
		conn.setRequestMethod("POST");   // 设置为POST发送方法
		conn.setRequestProperty("Connection", "Keep-Alive");//设置维持长连接
		conn.setRequestProperty("Charsert", "UTF-8");//设置文件字符集为UTF-8
		conn.setRequestProperty("Content-Type", MULTIPART_FORM_DATA                //设置文件类型
				  + ";boundary=" + BOUNDARY);
		//创建一个新的数据输出流,将数据写入指定的基础输出流
		DataOutputStream outstream = new DataOutputStream(conn.getOutputStream());
		if(FileName!="")   //发送文件数据
		{
			//定义StringBuilder对象构建发送字符串数据
			StringBuilder sb1 = new StringBuilder();
			sb1.append(PREFIX);
			sb1.append(BOUNDARY);
			sb1.append(LINEND);
			sb1.append("Content-Disposition: form-data;name=\"file1\"; filename=" + FileName + LINEND);
			sb1.append("Content-Type: application/octet-stream; charset="+ CHARSET + LINEND);
			sb1.append(LINEND);
			//写入输出流中
			outstream.write(sb1.toString().getBytes());
			//将文件读到输入流中
			InputStream is = new FileInputStream(FileName);
			byte[] buffer = new byte[1024];
			int len = 0;
			//写入输出流中		
			while((len=is.read(buffer))!=-1)
				
			{
				System.out.println(len);
				Log.v("len","keb");
				outstream.write(buffer,0,len);
			}
			is.close();//关闭输入流
			//添加换行标志
			outstream.write(LINEND.getBytes());
			
		}
		//请求结束标志
		byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
		outstream.write(end_data);
		//刷新,发送数据
		outstream.flush();
		//得到响应码
		int res = conn.getResponseCode();
		InputStream in = null;
		//上传成功返回相应码200
		if(res == 200)
		{
			Log.v("res","200");
			in = conn.getInputStream();
			int ch;
			StringBuilder sb2 = new StringBuilder();
			while((ch=in.read())!=-1)
			{
	
				sb2.append((char)ch);	
			}
			
		}
		return in==null?null:in.toString();
		
	}

}

代码具体解释看下注释吧,我出错的地方就是在 传递这句代码的时候出错的:sb1.append("Content-Disposition: form-data;name=\"file1\"; filename=" + FileName + LINEND);基于HTTP协议发送这个HTTP头,要有正确的格式,注意一下就好,要能够给filename一个正确的名字。这个filename是服务器端需要的参数,服务端通过这个参数值获得文件的名字。

接下来是Activity代码:

package com.example.uploadfile;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.example.filechooser.CallbackBundle;
import com.example.filechooser.OpenFileDialog;
import com.example.uploadfile.R;

import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.app.Dialog;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {


	public String url = "http://172.20.150.23/upload_file.php";
	public static Dialog dialog;
	public String uploadfilepath;
	public String uploadfilename;
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Button btn =(Button)findViewById(R.id.btn1);
		
		btn.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				
				new Thread(runnable).start();
			}
			
		});
	}
	Runnable runnable = new Runnable()
	{
		public void run()
		{
			String filename = uploadfilepath;//uploadfilepath是自己指定的上传文件的路径和名字
			try {
				Log.v("path",filename);
				String res=httppost.post(url,filename);
				Log.v("httres",res);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				Log.v("tag","error!");
				e.printStackTrace();
			}
		}
		
	};
  
     }  
	
	
}

这个代码比较简单就是定义了一个按钮点击上传即可。


你可能感兴趣的:(利用HTTP协议实现Android文件上传至WEB服务器,采用PHP接收文件(参考网上自己实现))