Android基于Http协议实现文件上传功能的方法
本文实例讲述了Android基于Http协议实现文件上传功能的方法。分享给大家供大家参考,具体如下:
注意一般使用Http协议上传的文件都比较小,一般是小于2M
这里示例是上传一个小的MP3文件
1.主Activity:MainActivity.java
publicclassMainActivityextendsActivity
{
privatestaticfinalStringTAG="MainActivity";
privateEditTexttimelengthText;
privateEditTexttitleText;
privateEditTextvideoText;
@Override
publicvoidonCreate(BundlesavedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//提交上传按钮
Buttonbutton=(Button)this.findViewById(R.id.button);
timelengthText=(EditText)this.findViewById(R.id.timelength);
videoText=(EditText)this.findViewById(R.id.video);
titleText=(EditText)this.findViewById(R.id.title);
button.setOnClickListener(newView.OnClickListener()
{
@Override
publicvoidonClick(Viewv)
{
Stringtitle=titleText.getText().toString();
Stringtimelength=timelengthText.getText().toString();
Map<String,String>params=newHashMap<String,String>();
params.put("method","save");
params.put("title",title);
params.put("timelength",timelength);
try
{
//得到SDCard的目录
FileuploadFile=newFile(Environment.getExternalStorageDirectory(),videoText.getText().toString());
//上传音频文件
FormFileformfile=newFormFile("02.mp3",uploadFile,"video","audio/mpeg");
SocketHttpRequester.post("http://192.168.1.100:8080/videoweb/video/manage.do",params,formfile);
Toast.makeText(MainActivity.this,R.string.success,1).show();
}
catch(Exceptione)
{
Toast.makeText(MainActivity.this,R.string.error,1).show();
Log.e(TAG,e.toString());
}
}
});
}
}
2.上传工具类,注意里面构造协议字符串需要根据不同的提交表单来处理
publicclassSocketHttpRequester
{
/**
*发送xml数据
*@parampath请求地址
*@paramxmlxml数据
*@paramencoding编码
*@return
*@throwsException
*/
publicstaticbyte[]postXml(Stringpath,Stringxml,Stringencoding)throwsException{
byte[]data=xml.getBytes(encoding);
URLurl=newURL(path);
HttpURLConnectionconn=(HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type","text/xml;charset="+encoding);
conn.setRequestProperty("Content-Length",String.valueOf(data.length));
conn.setConnectTimeout(5*1000);
OutputStreamoutStream=conn.getOutputStream();
outStream.write(data);
outStream.flush();
outStream.close();
if(conn.getResponseCode()==200){
returnreadStream(conn.getInputStream());
}
returnnull;
}
/**
*直接通过HTTP协议提交数据到服务器,实现如下面表单提交功能:
*<FORMMETHOD=POSTACTION="http://192.168.0.200:8080/ssi/fileload/test.do"enctype="multipart/form-data">
<INPUTTYPE="text"NAME="name">
<INPUTTYPE="text"NAME="id">
<inputtype="file"name="imagefile"/>
<inputtype="file"name="zip"/>
</FORM>
*@parampath上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,
*因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试)
*@paramparams请求参数key为参数名,value为参数值
*@paramfile上传文件
*/
publicstaticbooleanpost(Stringpath,Map<String,String>params,FormFile[]files)throwsException
{
//数据分隔线
finalStringBOUNDARY="---------------------------7da2137580612";
//数据结束标志"---------------------------7da2137580612--"
finalStringendline="--"+BOUNDARY+"--/r/n";
//下面两个for循环都是为了得到数据长度参数,依据表单的类型而定
//首先得到文件类型数据的总长度(包括文件分割线)
intfileDataLength=0;
for(FormFileuploadFile:files)
{
StringBuilderfileExplain=newStringBuilder();
fileExplain.append("--");
fileExplain.append(BOUNDARY);
fileExplain.append("/r/n");
fileExplain.append("Content-Disposition:form-data;name=/""+uploadFile.getParameterName()+"/";filename=/""+uploadFile.getFilname()+"/"/r/n");
fileExplain.append("Content-Type:"+uploadFile.getContentType()+"/r/n/r/n");
fileExplain.append("/r/n");
fileDataLength+=fileExplain.length();
if(uploadFile.getInStream()!=null){
fileDataLength+=uploadFile.getFile().length();
}else{
fileDataLength+=uploadFile.getData().length;
}
}
//再构造文本类型参数的实体数据
StringBuildertextEntity=newStringBuilder();
for(Map.Entry<String,String>entry:params.entrySet())
{
textEntity.append("--");
textEntity.append(BOUNDARY);
textEntity.append("/r/n");
textEntity.append("Content-Disposition:form-data;name=/""+entry.getKey()+"/"/r/n/r/n");
textEntity.append(entry.getValue());
textEntity.append("/r/n");
}
//计算传输给服务器的实体数据总长度(文本总长度+数据总长度+分隔符)
intdataLength=textEntity.toString().getBytes().length+fileDataLength+endline.getBytes().length;
URLurl=newURL(path);
//默认端口号其实可以不写
intport=url.getPort()==-1?80:url.getPort();
//建立一个Socket链接
Socketsocket=newSocket(InetAddress.getByName(url.getHost()),port);
//获得一个输出流(从Android流到web)
OutputStreamoutStream=socket.getOutputStream();
//下面完成HTTP请求头的发送
Stringrequestmethod="POST"+url.getPath()+"HTTP/1.1/r/n";
outStream.write(requestmethod.getBytes());
//构建accept
Stringaccept="Accept:image/gif,image/jpeg,image/pjpeg,image/pjpeg,application/x-shockwave-flash,application/xaml+xml,application/vnd.ms-xpsdocument,application/x-ms-xbap,application/x-ms-application,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,*/*/r/n";
outStream.write(accept.getBytes());
//构建language
Stringlanguage="Accept-Language:zh-CN/r/n";
outStream.write(language.getBytes());
//构建contenttype
Stringcontenttype="Content-Type:multipart/form-data;boundary="+BOUNDARY+"/r/n";
outStream.write(contenttype.getBytes());
//构建contentlength
Stringcontentlength="Content-Length:"+dataLength+"/r/n";
outStream.write(contentlength.getBytes());
//构建alive
Stringalive="Connection:Keep-Alive/r/n";
outStream.write(alive.getBytes());
//构建host
Stringhost="Host:"+url.getHost()+":"+port+"/r/n";
outStream.write(host.getBytes());
//写完HTTP请求头后根据HTTP协议再写一个回车换行
outStream.write("/r/n".getBytes());
//把所有文本类型的实体数据发送出来
outStream.write(textEntity.toString().getBytes());
//把所有文件类型的实体数据发送出来
for(FormFileuploadFile:files)
{
StringBuilderfileEntity=newStringBuilder();
fileEntity.append("--");
fileEntity.append(BOUNDARY);
fileEntity.append("/r/n");
fileEntity.append("Content-Disposition:form-data;name=/""+uploadFile.getParameterName()+"/";filename=/""+uploadFile.getFilname()+"/"/r/n");
fileEntity.append("Content-Type:"+uploadFile.getContentType()+"/r/n/r/n");
outStream.write(fileEntity.toString().getBytes());
//边读边写
if(uploadFile.getInStream()!=null)
{
byte[]buffer=newbyte[1024];
intlen=0;
while((len=uploadFile.getInStream().read(buffer,0,1024))!=-1)
{
outStream.write(buffer,0,len);
}
uploadFile.getInStream().close();
}
else
{
outStream.write(uploadFile.getData(),0,uploadFile.getData().length);
}
outStream.write("/r/n".getBytes());
}
//下面发送数据结束标志,表示数据已经结束
outStream.write(endline.getBytes());
BufferedReaderreader=newBufferedReader(newInputStreamReader(socket.getInputStream()));
//读取web服务器返回的数据,判断请求码是否为200,如果不是200,代表请求失败
if(reader.readLine().indexOf("200")==-1)
{
returnfalse;
}
outStream.flush();
outStream.close();
reader.close();
socket.close();
returntrue;
}
/**
*提交数据到服务器
*@parampath上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试)
*@paramparams请求参数key为参数名,value为参数值
*@paramfile上传文件
*/
publicstaticbooleanpost(Stringpath,Map<String,String>params,FormFilefile)throwsException
{
returnpost(path,params,newFormFile[]{file});
}
/**
*提交数据到服务器
*@parampath上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试)
*@paramparams请求参数key为参数名,value为参数值
*@paramencode编码
*/
publicstaticbyte[]postFromHttpClient(Stringpath,Map<String,String>params,Stringencode)throwsException
{
//用于存放请求参数
List<NameValuePair>formparams=newArrayList<NameValuePair>();
for(Map.Entry<String,String>entry:params.entrySet())
{
formparams.add(newBasicNameValuePair(entry.getKey(),entry.getValue()));
}
UrlEncodedFormEntityentity=newUrlEncodedFormEntity(formparams,encode);
HttpPosthttppost=newHttpPost(path);
httppost.setEntity(entity);
//看作是浏览器
HttpClienthttpclient=newDefaultHttpClient();
//发送post请求
HttpResponseresponse=httpclient.execute(httppost);
returnreadStream(response.getEntity().getContent());
}
/**
*发送请求
*@parampath请求路径
*@paramparams请求参数key为参数名称value为参数值
*@paramencode请求参数的编码
*/
publicstaticbyte[]post(Stringpath,Map<String,String>params,Stringencode)throwsException
{
//Stringparams="method=save&name="+URLEncoder.encode("老毕","UTF-8")+"&age=28&";//需要发送的参数
StringBuilderparambuilder=newStringBuilder("");
if(params!=null&&!params.isEmpty())
{
for(Map.Entry<String,String>entry:params.entrySet())
{
parambuilder.append(entry.getKey()).append("=")
.append(URLEncoder.encode(entry.getValue(),encode)).append("&");
}
parambuilder.deleteCharAt(parambuilder.length()-1);
}
byte[]data=parambuilder.toString().getBytes();
URLurl=newURL(path);
HttpURLConnectionconn=(HttpURLConnection)url.openConnection();
//设置允许对外发送请求参数
conn.setDoOutput(true);
//设置不进行缓存
conn.setUseCaches(false);
conn.setConnectTimeout(5*1000);
conn.setRequestMethod("POST");
//下面设置http请求头
conn.setRequestProperty("Accept","image/gif,image/jpeg,image/pjpeg,image/pjpeg,application/x-shockwave-flash,application/xaml+xml,application/vnd.ms-xpsdocument,application/x-ms-xbap,application/x-ms-application,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,*/*");
conn.setRequestProperty("Accept-Language","zh-CN");
conn.setRequestProperty("User-Agent","Mozilla/4.0(compatible;MSIE8.0;WindowsNT5.2;Trident/4.0;.NETCLR1.1.4322;.NETCLR2.0.50727;.NETCLR3.0.04506.30;.NETCLR3.0.4506.2152;.NETCLR3.5.30729)");
conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length",String.valueOf(data.length));
conn.setRequestProperty("Connection","Keep-Alive");
//发送参数
DataOutputStreamoutStream=newDataOutputStream(conn.getOutputStream());
outStream.write(data);//把参数发送出去
outStream.flush();
outStream.close();
if(conn.getResponseCode()==200)
{
returnreadStream(conn.getInputStream());
}
returnnull;
}
/**
*读取流
*@paraminStream
*@return字节数组
*@throwsException
*/
publicstaticbyte[]readStream(InputStreaminStream)throwsException
{
ByteArrayOutputStreamoutSteam=newByteArrayOutputStream();
byte[]buffer=newbyte[1024];
intlen=-1;
while((len=inStream.read(buffer))!=-1)
{
outSteam.write(buffer,0,len);
}
outSteam.close();
inStream.close();
returnoutSteam.toByteArray();
}
}
publicclassStreamTool
{
/**
*从输入流读取数据
*@paraminStream
*@return
*@throwsException
*/
publicstaticbyte[]readInputStream(InputStreaminStream)throwsException{
ByteArrayOutputStreamoutSteam=newByteArrayOutputStream();
byte[]buffer=newbyte[1024];
intlen=0;
while((len=inStream.read(buffer))!=-1){
outSteam.write(buffer,0,len);
}
outSteam.close();
inStream.close();
returnoutSteam.toByteArray();
}
}
/**
*使用JavaBean封装上传文件数据
*
*/
publicclassFormFile
{
//上传文件的数据
privatebyte[]data;
privateInputStreaminStream;
privateFilefile;
//文件名称
privateStringfilname;
//请求参数名称
privateStringparameterName;
//内容类型
privateStringcontentType="application/octet-stream";
/**
*上传小文件,把文件数据先读入内存
*@paramfilname
*@paramdata
*@paramparameterName
*@paramcontentType
*/
publicFormFile(Stringfilname,byte[]data,StringparameterName,StringcontentType)
{
this.data=data;
this.filname=filname;
this.parameterName=parameterName;
if(contentType!=null)this.contentType=contentType;
}
/**
*上传大文件,一边读文件数据一边上传
*@paramfilname
*@paramfile
*@paramparameterName
*@paramcontentType
*/
publicFormFile(Stringfilname,Filefile,StringparameterName,StringcontentType)
{
this.filname=filname;
this.parameterName=parameterName;
this.file=file;
try
{
this.inStream=newFileInputStream(file);
}
catch(FileNotFoundExceptione)
{
e.printStackTrace();
}
if(contentType!=null)this.contentType=contentType;
}
publicFilegetFile()
{
returnfile;
}
publicInputStreamgetInStream()
{
returninStream;
}
publicbyte[]getData()
{
returndata;
}
publicStringgetFilname()
{
returnfilname;
}
publicvoidsetFilname(Stringfilname)
{
this.filname=filname;
}
publicStringgetParameterName()
{
returnparameterName;
}
publicvoidsetParameterName(StringparameterName)
{
this.parameterName=parameterName;
}
publicStringgetContentType()
{
returncontentType;
}
publicvoidsetContentType(StringcontentType)
{
this.contentType=contentType;
}
}
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android文件操作技巧汇总》、《Android操作SQLite数据库技巧总结》、《Android操作json格式数据技巧总结》、《Android数据库操作技巧总结》、《Android编程之activity操作技巧总结》、《Android编程开发之SD卡操作方法汇总》、《Android开发入门与进阶教程》、《Android资源操作技巧汇总》、《Android视图View技巧总结》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。