您的位置:首页 > 理论基础 > 计算机网络

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

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

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题文档</title>
</head>

<body>
<span style="color:#ff0000;"><form action="upload_file.php" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file1" id="file" />
<br/>
<input type="submit" name="submit" value="提交" />
</form></span>
</body>
</html>


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

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

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

图片来源与书上。

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

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题文档</title>
</head>

<body>
<span style="color:#ff0000;"><?php
if($_FILES["file1"]["size"]<20000)               //文件大小控制在20000字节内,超出则不接受,这个可以自己改。
{
if($_FILES["file1"]["error"]>0)           //上传文件的错误代码,如果返回了错位代码可以对照错误信息进行修正
{
echo "Return Code:".$_FILES["file1"]["error"]."<br />";

}
else
{

echo "Upload: ".$_FILES["file1"]["name"]."<br />";        //显示文件的名字,类型,大小,临时存放文件的路径
echo "Type: ".$_FILES["file1"]["type"]."<br />";
echo "Size: ".($_FILES["file1"]["size"]/1024)."kb<br />";
echo "Temp file1:".$_FILES["file1"]["tmp_name"]."<br />";
if(file_exists("./upload/".$_FILES["file1"]["name"]))        //检测文件是否存在于upload目录下(这个目录是用来存放上传文件的目录,也是建立<span style="white-space:pre">									</span>在WWW目录下的),如果存在则返回提示。
{
echo $_FILES["file1"]["name"]."already existst!";
}
else
{</span>
<span style="color:#ff0000;"></span><pre name="code" class="php" style="color: rgb(255, 0, 0); ">//调用了一个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字节则提示出错。}?></body></html>


还是红色代码为写的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";  <span style="white-space:pre">				</span>//字符编码

URL url = new URL(actionurl);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();//建立HTTP连接
conn.setReadTimeout(5*1000);   <span style="white-space:pre">	</span>//设置从主机读取数据超时时间 单位:毫秒
conn.setDoInput(true);<span style="white-space:pre">		</span>//设置允许输入
conn.setDoOutput(true);<span style="white-space:pre">		</span>//设置允许输出
conn.setUseCaches(false);<span style="white-space:pre">	</span>//设置不使用缓存
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);
<span style="white-space:pre">		</span>//创建一个新的数据输出流,将数据写入指定的基础输出流
DataOutputStream outstream = new DataOutputStream(conn.getOutputStream());
if(FileName!="")   //发送文件数据
{
<span style="white-space:pre">			</span>//定义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;
<span style="white-space:pre">			</span>//写入输出流中<span style="white-space:pre">		</span>
while((len=is.read(buffer))!=-1)

{
System.out.println(len);
Log.v("len","keb");
outstream.write(buffer,0,len);
}
is.close();//关闭输入流
<span style="white-space:pre">			</span>//添加换行标志
outstream.write(LINEND.getBytes());

}
//请求结束标志
byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
outstream.write(end_data);
<span style="white-space:pre">		</span>//刷新,发送数据
outstream.flush();
<span style="white-space:pre">		</span>//得到响应码
int res = conn.getResponseCode();
InputStream in = null;
<span style="white-space:pre">		</span>//上传成功返回相应码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();
}
}

};

}

}


这个代码比较简单就是定义了一个按钮点击上传即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: