28_网络通信之通过HTTP协议实现文件上传
----------------------------------------------
1.注意,做表单提交的时候:程序代码;
<form method="post"
action="http://192.168.1.110:6118/WebGetSetTest/ManagerServlet"
enctype="multipart/form-data">
标题<input name="title" type="text"/><br/>
时长<input name="timelength" type="text"/><br/>
文件<input name="videofile" type="file"/><br/>
<input value="提交" type="submit"/>
</form>
----------------------------------------------------------------
2.注意在http://192.168.1.110:6118/WebGetSetTest/
http协议,post指定post方法的时候:boundary=-----------------
是指定的数据的分割线.根据http协议的要求:
数据之间要多加两个--号
---------------------------------
3.用IE捕获的信息:
a.请求标头:
键 值
请求 POST /WebGetSetTest/ManagerServlet HTTP/1.1
Accept text/html, application/xhtml+xml, */*
Referer http://192.168.1.110:6118/WebGetSetTest/
Accept-Language zh-CN
User-Agent Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Content-Type multipart/form-data;
boundary= ---------------------------7dd33a32e07fc//是指定的数据的分割线
Accept-Encoding gzip, deflate
Host 192.168.1.110:6118
Content-Length 14052
Connection Keep-Alive
Cache-Control no-cache
Cookie JSESSIONID=424D8985791F17DAF67D00AC1FFF26BC
-----------------------------------------------------------------------
b.请求正文:
-----------------------------7dd33a32e07fc//是指定的数据的分割线,比上面的多了两
//个--,这是协议规定的
Content-Disposition: form-data; name="title"//指定了参数的名称
lidewei//这是参数的值,参数描述和值之间有两个回车换行
-----------------------------7dd33a32e07fc//是指定的数据的分割线
Content-Disposition: form-data; name="timelength"
598
-----------------------------7dd33a32e07fc
Content-Disposition: form-data; name="videofile"; filename="2.png"
Content-Type: image/jpeg//内容类型
<二进制文件数据未显示>//这里是内容信息
-----------------------------7dd33a32e07fc--//结束线后面有两个--
--------------------------------------------------------
c.响应标头
键 值
响应 HTTP/1.1 200 OK
Server Apache-Coyote/1.1
Content-Length 0
Date Thu, 28 Mar 2013 13:57:51 GMT
---------------------------------------------------
d.关于http协议,post的方法:封装的代码:
可以做为一个通用的方法以后用:
-----------------------------------------
2013-03-29
-----------------------
com.credream.utils
/HttpFileUpload/src/com/credream/utils/FormFile.java
-------------------------------------------------------------
package com.credream.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* 上传文件
*/
public class FormFile {
/* 上传文件的数据 */
private byte[] data;
private InputStream inStream;
private File file;
/* 文件名称 */
private String filname;
/* 请求参数名称*/
private String parameterName;
/* 内容类型 */
private String contentType = "application/octet-stream";
//文件比较小的时候用这个方法,这时候就是直接把内存中的数据拿出来,放到磁盘
上
public FormFile(String filname, byte[] data, String parameterName, String
contentType) {
this.data = data;
this.filname = filname;
this.parameterName = parameterName;
if(contentType!=null) this.contentType = contentType;
}
//要求传入文件的对象,实现一边读文件,一边上传写到磁盘上,这样不会占用太多内
存,
//上传大文件的时候,一定要用这个方式.
public FormFile(File file, String parameterName, String contentType) {
this.filname = file.getName();
this.parameterName = parameterName;
this.file = file;
try {
this.inStream = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if(contentType!=null) this.contentType = contentType;
}
public File getFile() {
return file;
}
public InputStream getInStream() {
return inStream;
}
public byte[] getData() {
return data;
}
public String getFilname() {
return filname;
}
public void setFilname(String filname) {
this.filname = filname;
}
public String getParameterName() {
return parameterName;
}
public void setParameterName(String parameterName) {
this.parameterName = parameterName;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
}
---------------------------------------------------------------
b./HttpFileUpload/src/com/credream/utils/SocketHttpRequester.java
package com.credream.utils;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
//Content-Length注意这里计算实体数据的总长度的时候,很费劲的,因为
//比如说实体数据为100m的话,那么不可能一次的在内存中得到100m数据的总长度,然后赋值
给
//Content-Length属性.
/*这里需要用到一些技巧:
先计算,文本类型参数的总长度,然后计算文件类型参数的总长度,然后加上分割线的
总长度
*/
public class SocketHttpRequester {
/**
* 直接通过HTTP协议提交数据到服务器,实现如下面表单提交功能:
* <FORM METHOD=POST
ACTION="http://192.168.0.200:8080/ssi/fileload/test.do" enctype="multipart/form-
data">
<INPUT TYPE="text" NAME="name">
<INPUT TYPE="text" NAME="id">
<input type="file" name="imagefile"/>
<input type="file" name="zip"/>
</FORM>
* @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,
因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080
这样的路径测试)
* @param params 请求参数 key为参数名,value为参数值
* @param file 上传文件
*/
public static boolean post(String path, Map<String, String> params,
FormFile[] files) throws Exception{
final String BOUNDARY = "---------------------------7da2137580612"; //数
据分隔线
final String endline = "--" + BOUNDARY + "--\r\n";//数据结束标志//注意回
车换行部分
int fileDataLength = 0;
for(FormFile uploadFile : files){//得到文件类型数据的总长度
StringBuilder fileExplain = new StringBuilder();
fileExplain.append("--");
fileExplain.append(BOUNDARY);
fileExplain.append("\r\n");
//以上部分用来完成分割线: -----------------------------
7dd33a32e07fc
//注意这里的回车换行
fileExplain.append("Content-Disposition: form-data;name=\""+
uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r
\n");
fileExplain.append("Content-Type: "+ uploadFile.getContentType
()+"\r\n\r\n");
//上面两行用来
/* Content-Disposition: form-data; name="videofile"; filename="2.png"
Content-Type: image/jpeg*/
fileDataLength += fileExplain.length();
/*//通过上面就可以计算下面这个部分的总长度了
-----------------------------7dd33a32e07fc
Content-Disposition: form-data; name="videofile"; filename="2.png"
Content-Type: image/jpeg*/
if(uploadFile.getInStream()!=null){
fileDataLength += uploadFile.getFile().length();
}else{
fileDataLength += uploadFile.getData().length;
}
fileDataLength += "\r\n".length();
}
StringBuilder textEntity = new StringBuilder();
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");
}
//计算传输给服务器的实体数据总长度
int dataLength = textEntity.toString().getBytes().length + fileDataLength
+ endline.getBytes().length;
URL url = new URL(path);
int port = url.getPort()==-1 ? 80 : url.getPort();
//这里没有用HttpUrlConnection来做,而是直接用socket来做
//因为HttpUrlConnection使用了缓冲技术,通过这个类给web,应用发送文件的时候
//这个时候文件首先写入到缓冲里面,很可能导致内存溢出的情况.
//Socket比HttpUrlConnection底层,没有缓冲区限制
Socket socket = new Socket(InetAddress.getByName(url.getHost()), port);
OutputStream outStream = socket.getOutputStream();
//下面完成HTTP请求头的发送
String requestmethod = "POST "+ url.getPath()+" HTTP/1.1\r\n";
outStream.write(requestmethod.getBytes());
String accept = "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());
String language = "Accept-Language: zh-CN\r\n";
outStream.write(language.getBytes());
String contenttype = "Content-Type: multipart/form-data; boundary="+
BOUNDARY+ "\r\n";
outStream.write(contenttype.getBytes());
String contentlength = "Content-Length: "+ dataLength + "\r\n";
outStream.write(contentlength.getBytes());
String alive = "Connection: Keep-Alive\r\n";
outStream.write(alive.getBytes());
String host = "Host: "+ url.getHost() +":"+ port +"\r\n";
outStream.write(host.getBytes());
//写完HTTP请求头后根据HTTP协议再写一个回车换行
outStream.write("\r\n".getBytes());
//把所有文本类型的实体数据发送出来
outStream.write(textEntity.toString().getBytes());
//把所有文件类型的实体数据发送出来
for(FormFile uploadFile : files){
StringBuilder fileEntity = new StringBuilder();
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 = new byte[1024];
int len = 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());
BufferedReader reader = new BufferedReader(new InputStreamReader
(socket.getInputStream()));
if(reader.readLine().indexOf("200")==-1){//读取web服务器返回的数据,判断
请求码是否为200,如果不是200,代表请求失败
return false;
}
outStream.flush();
outStream.close();
reader.close();
socket.close();
return true;
}
/**
* 提交数据到服务器
* @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,
因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080
这样的路径测试)
* @param params 请求参数 key为参数名,value为参数值
* @param file 上传文件
*/
public static boolean post(String path, Map<String, String> params,
FormFile file) throws Exception{
return post(path, params, new FormFile[]{file});
}
/**
* 提交数据到服务器
* @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,
因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080
这样的路径测试)
* @param params 请求参数 key为参数名,value为参数值
* @param encode 编码
*/
public static byte[] postFromHttpClient(String path, Map<String, String>
params, String encode) throws Exception{
List<NameValuePair> formparams = new ArrayList<NameValuePair>
();//用于存放请求参数
for(Map.Entry<String, String> entry : params.entrySet()){
formparams.add(new BasicNameValuePair(entry.getKey(),
entry.getValue()));
}
UrlEncodedFormEntity entity = new UrlEncodedFormEntity
(formparams, encode);
HttpPost httppost = new HttpPost(path);
httppost.setEntity(entity);
HttpClient httpclient = new DefaultHttpClient();//看作是浏览器
HttpResponse response = httpclient.execute(httppost);//发送post请
求
return readStream(response.getEntity().getContent());
}
/**
* 发送请求
* @param path 请求路径
* @param params 请求参数 key为参数名称 value为参数值
* @param encode 请求参数的编码
*/
public static byte[] post(String path, Map<String, String> params, String
encode) throws Exception{
//String params = "method=save&name="+ URLEncoder.encode("老毕",
"UTF-8")+ "&age=28&";//需要发送的参数
StringBuilder parambuilder = new StringBuilder("");
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();
URL url = new URL(path);
HttpURLConnection conn = (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;
MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727;
.NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
conn.setRequestProperty("Content-Type", "application/x-www-form-
urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf
(data.length));
conn.setRequestProperty("Connection", "Keep-Alive");
//发送参数
DataOutputStream outStream = new DataOutputStream
(conn.getOutputStream());
outStream.write(data);//把参数发送出去
outStream.flush();
outStream.close();
if(conn.getResponseCode()==200){
return readStream(conn.getInputStream());
}
return null;
}
/**
* 读取流
* @param inStream
* @return 字节数组
* @throws Exception
*/
public static byte[] readStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while( (len=inStream.read(buffer)) != -1){
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
return outSteam.toByteArray();
}
}
----------------------------------------------------------------
2.对于:28_网络通信之通过HTTP协议实现文件上传的所有代码
-----------------------------------------
1.新建Android项目:HttpFileUpload项目
---------------
/HttpFileUpload/src/com/credream/newmanager/NewsGetSetManagerActivity.java
package com.credream.newmanager;
import java.io.File;
import com.credream.service.NewsService;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class NewsGetSetManagerActivity extends Activity {
/** Called when the activity is first created. */
private EditText titleText;
private EditText timelengthText;
private EditText nameText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
titleText=(EditText) this.findViewById(R.id.title);
timelengthText= (EditText)this.findViewById(R.id.timelength);
nameText= (EditText)this.findViewById(R.id.filename);
}
public void save(View v){
String filename= nameText.getText().toString();
String title= titleText.getText().toString();
String length=timelengthText.getText().toString();
//判断有没有sd卡,当有sd卡,和sd为只读的时候,可以执行
if(Environment.getExternalStorageState().equals
(Environment.MEDIA_MOUNTED)||
Environment.getExternalStorageState().equals
(Environment.MEDIA_MOUNTED_READ_ONLY)){
File uploadFile =
new File(Environment.getExternalStorageDirectory
(),filename);
if(uploadFile.exists()){//调用方法进行保存文件
boolean result=
NewsService.save(title,length,uploadFile);
if(result){//
Toast.makeText(getApplicationContext(), R.string.success, 1).show();
}else {
Toast.makeText(getApplicationContext(), R.string.error, 1).show();
}
}else {
Toast.makeText(getApplicationContext(), R.string.filenoexsit, 1).show();
}
}else {//当sdk不存在的时候
boolean result=NewsService.save(title,length);//用这样业务类,进行
保存
if(result){
Toast.makeText(getApplicationContext(), R.string.success,1).show
();
}else {
Toast.makeText(getApplicationContext(), R.string.error, 1).show
();
}
}
}
}
------------------------------------------------------------------------------
2./HttpFileUpload/src/com/credream/service/NewsService.java
package com.credream.service;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import com.credream.utils.FormFile;
import com.credream.utils.SocketHttpRequester;
import android.media.MediaRecorder.OutputFormat;
import android.provider.ContactsContract.Contacts.Data;
public class NewsService
{
/**
* 保存数据
* @param title 标题
* @param length 时长
* @return
*/
public static boolean save(String title, String length)
{
String
path="http://192.168.1.110:6118/WebGetSetTest/ManagerServlet";
Map<String, String> params=new HashMap<String, String>();
params.put("title", title);
params.put("timelength", length);
try{
//return sendGetRequest(path,params);
//return sendGetRequest(path,params,"UTF-8");
//return sendPOSTRequest(path,params,"UTF-8");
return sendHttpClientRequest(path,params,"UTF-8");
}catch(Exception e){
e.printStackTrace();
}
return false;
}
/**通过httpClient的时候,发送post请求
*使用httpClient的时候,不需要导入jar文件,因为android,已经集成了这个功能
* @param path
* @param params
* @param string
* @return
* @throws IOException
*/
private static boolean sendHttpClientRequest(String path,
Map<String, String> params, String coding) throws
IOException
{
List<NameValuePair> pairs=new ArrayList<NameValuePair>();//存放请
求参数
if(params!=null && !params.isEmpty()){
for(Map.Entry<String, String> entry:params.entrySet()){
pairs.add(new BasicNameValuePair(entry.getKey(),
entry.getValue()));
}
}
//采用
//编码
UrlEncodedFormEntity entity=new UrlEncodedFormEntity
(pairs,coding);
HttpPost httpPost=new HttpPost(path);
httpPost.setEntity(entity);
DefaultHttpClient client=new DefaultHttpClient();
//可以看做一个浏览器
HttpResponse response=client.execute(httpPost);
if (response.getStatusLine().getStatusCode()==200)
{
return true;
}
return false;
}
/**
* 发送post请求
* @param path 请求路径
* @param params 请求参数
* @param string 编码
* @return 请求是否成功
* @throws Exception
*/
private static boolean sendPOSTRequest(String path,Map<String, String> params,
String coding) throws Exception
{
//title=lidewei&timelength=90
StringBuilder data=new StringBuilder();
if(params!=null && !params.isEmpty()){
for(Map.Entry<String, String> entry:params.entrySet()){
data.append(entry.getKey()).append("=");
//url.append(entry.getValue());
data.append(URLEncoder.encode(entry.getValue(), coding));
//乱码的第一个因素,对传来的字符串进行编码
data.append("&");
}
data.deleteCharAt(data.length()-1);
}
byte[] entity=data.toString().getBytes();//得到实体数据
HttpURLConnection conn= (HttpURLConnection) new URL(path).openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("POST");
conn.setDoOutput(true);//允许
conn.setRequestProperty("Content-Type", "application/x-www-form-
urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(entity.length));
OutputStream outputStream=conn.getOutputStream();
outputStream.write(entity);//数据写到了缓存中
//只有在我们取得响应的http协议的某个部分的时候,请求才会真正的发送出去.
if (conn.getResponseCode()==200)
{
return true;
}
return false;
}
//组拼字符串http://localhost:6118/WebGetSetTest/ManagerServlet?
title=xiaofeng&timelength=80
/**
* 发送GET请求
* @param path 请求路径
* @param params 请求参数
* @return 请求是否成功
* @throws Exception
*/
//private static boolean sendGetRequest(String path,Map<String, String>
params)throws Exception{
//没有修改前会出现乱码
private static boolean sendGetRequest(String path,Map<String, String>
params,String coding)throws Exception{
StringBuilder url=new StringBuilder(path);
url.append("?");
for(Map.Entry<String, String> entry:params.entrySet()){
url.append(entry.getKey()).append("=");
//url.append(entry.getValue());
url.append(URLEncoder.encode(entry.getValue(), coding));
//乱码的第一个因素,对传来的字符串进行编码
//
url.append("&");
}
url.deleteCharAt(url.length()-1);
HttpURLConnection conn=(HttpURLConnection)new URL(url.toString
()).openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if(conn.getResponseCode()==200){
return true;
}
return false;
}
//用来上传文件的save方法测试
public static boolean save(String title, String length, File uploadFile)
{
String path="http://192.168.1.110:6118/WebGetSetTest/ManagerServlet";
Map<String, String> params=new HashMap<String, String>();
params.put("title", title);
params.put("timelength", length);
FormFile formFile=new FormFile(uploadFile, "videofile", "image/gif");
//jpg的就写 "image/jpeg"
//注意这里的第三个参数类型,如果想根据用户输入不同文件,比如用户输入的事
图片文件
//对应的类型就是image/jpeg,用户输入的是可执行文件exe,对应的就是....
//那么这里需要建立字典,比如tomcat就是通过建立字典判断文件类型的
/*//
* 在tomcat的配置文件中:G:\apache-tomcat-6.0.10\conf\web.xml
<mime-mapping>
<extension>jpeg</extension>
<mime-type>image/jpeg</mime-type>
</mime-mapping>
<mime-mapping>
<extension>jpg</extension>
<mime-type>image/jpeg</mime-type>
</mime-mapping>*/
try{
return SocketHttpRequester.post(path,params,formFile);
}catch(Exception e){
e.printStackTrace();
}
return false;
//这个方法.
}
}
-------------------------------------------------------------------------
3./HttpFileUpload/src/com/credream/utils/FormFile.java
package com.credream.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* 上传文件
*/
public class FormFile {
/* 上传文件的数据 */
private byte[] data;
private InputStream inStream;
private File file;
/* 文件名称 */
private String filname;
/* 请求参数名称*/
private String parameterName;
/* 内容类型 */
private String contentType = "application/octet-stream";
//文件比较小的时候用这个方法,这时候就是直接把内存中的数据拿出来,放到磁盘
上
public FormFile(String filname, byte[] data, String parameterName, String
contentType) {
this.data = data;
this.filname = filname;
this.parameterName = parameterName;
if(contentType!=null) this.contentType = contentType;
}
//要求传入文件的对象,实现一边读文件,一边上传写到磁盘上,这样不会占用太多内
存,
//上传大文件的时候,一定要用这个方式.
public FormFile(File file, String parameterName, String contentType) {
this.filname = file.getName();
this.parameterName = parameterName;
this.file = file;
try {
this.inStream = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if(contentType!=null) this.contentType = contentType;
}
public File getFile() {
return file;
}
public InputStream getInStream() {
return inStream;
}
public byte[] getData() {
return data;
}
public String getFilname() {
return filname;
}
public void setFilname(String filname) {
this.filname = filname;
}
public String getParameterName() {
return parameterName;
}
public void setParameterName(String parameterName) {
this.parameterName = parameterName;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
}
----------------------------------------------------------------------
4./HttpFileUpload/src/com/credream/utils/SocketHttpRequester.java
package com.credream.utils;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
//Content-Length注意这里计算实体数据的总长度的时候,很费劲的,因为
//比如说实体数据为100m的话,那么不可能一次的在内存中得到100m数据的总长度,然后赋值
给
//Content-Length属性.
/*这里需要用到一些技巧:
先计算,文本类型参数的总长度,然后计算文件类型参数的总长度,然后加上分割线的
总长度
*/
public class SocketHttpRequester {
/**
* 直接通过HTTP协议提交数据到服务器,实现如下面表单提交功能:
* <FORM METHOD=POST
ACTION="http://192.168.0.200:8080/ssi/fileload/test.do" enctype="multipart/form-
data">
<INPUT TYPE="text" NAME="name">
<INPUT TYPE="text" NAME="id">
<input type="file" name="imagefile"/>
<input type="file" name="zip"/>
</FORM>
* @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,
因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080
这样的路径测试)
* @param params 请求参数 key为参数名,value为参数值
* @param file 上传文件
*/
public static boolean post(String path, Map<String, String> params,
FormFile[] files) throws Exception{
final String BOUNDARY = "---------------------------7da2137580612"; //数
据分隔线
final String endline = "--" + BOUNDARY + "--\r\n";//数据结束标志//注意回
车换行部分
int fileDataLength = 0;
for(FormFile uploadFile : files){//得到文件类型数据的总长度
StringBuilder fileExplain = new StringBuilder();
fileExplain.append("--");
fileExplain.append(BOUNDARY);
fileExplain.append("\r\n");
//以上部分用来完成分割线: -----------------------------
7dd33a32e07fc
//注意这里的回车换行
fileExplain.append("Content-Disposition: form-data;name=\""+
uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r
\n");
fileExplain.append("Content-Type: "+ uploadFile.getContentType
()+"\r\n\r\n");
//上面两行用来
/* Content-Disposition: form-data; name="videofile"; filename="2.png"
Content-Type: image/jpeg*/
fileDataLength += fileExplain.length();
/*//通过上面就可以计算下面这个部分的总长度了
-----------------------------7dd33a32e07fc
Content-Disposition: form-data; name="videofile"; filename="2.png"
Content-Type: image/jpeg*/
if(uploadFile.getInStream()!=null){
fileDataLength += uploadFile.getFile().length();
}else{
fileDataLength += uploadFile.getData().length;
}
fileDataLength += "\r\n".length();
}
StringBuilder textEntity = new StringBuilder();
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");
}
//计算传输给服务器的实体数据总长度
int dataLength = textEntity.toString().getBytes().length + fileDataLength
+ endline.getBytes().length;
URL url = new URL(path);
int port = url.getPort()==-1 ? 80 : url.getPort();
//这里没有用HttpUrlConnection来做,而是直接用socket来做
//因为HttpUrlConnection使用了缓冲技术,通过这个类给web,应用发送文件的时候
//这个时候文件首先写入到缓冲里面,很可能导致内存溢出的情况.
//Socket比HttpUrlConnection底层,没有缓冲区限制
Socket socket = new Socket(InetAddress.getByName(url.getHost()), port);
OutputStream outStream = socket.getOutputStream();
//下面完成HTTP请求头的发送
String requestmethod = "POST "+ url.getPath()+" HTTP/1.1\r\n";
outStream.write(requestmethod.getBytes());
String accept = "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());
String language = "Accept-Language: zh-CN\r\n";
outStream.write(language.getBytes());
String contenttype = "Content-Type: multipart/form-data; boundary="+
BOUNDARY+ "\r\n";
outStream.write(contenttype.getBytes());
String contentlength = "Content-Length: "+ dataLength + "\r\n";
outStream.write(contentlength.getBytes());
String alive = "Connection: Keep-Alive\r\n";
outStream.write(alive.getBytes());
String host = "Host: "+ url.getHost() +":"+ port +"\r\n";
outStream.write(host.getBytes());
//写完HTTP请求头后根据HTTP协议再写一个回车换行
outStream.write("\r\n".getBytes());
//把所有文本类型的实体数据发送出来
outStream.write(textEntity.toString().getBytes());
//把所有文件类型的实体数据发送出来
for(FormFile uploadFile : files){
StringBuilder fileEntity = new StringBuilder();
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 = new byte[1024];
int len = 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());
BufferedReader reader = new BufferedReader(new InputStreamReader
(socket.getInputStream()));
if(reader.readLine().indexOf("200")==-1){//读取web服务器返回的数据,判断
请求码是否为200,如果不是200,代表请求失败
return false;
}
outStream.flush();
outStream.close();
reader.close();
socket.close();
return true;
}
/**
* 提交数据到服务器
* @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,
因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080
这样的路径测试)
* @param params 请求参数 key为参数名,value为参数值
* @param file 上传文件
*/
public static boolean post(String path, Map<String, String> params,
FormFile file) throws Exception{
return post(path, params, new FormFile[]{file});
}
/**
* 提交数据到服务器
* @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,
因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080
这样的路径测试)
* @param params 请求参数 key为参数名,value为参数值
* @param encode 编码
*/
public static byte[] postFromHttpClient(String path, Map<String, String>
params, String encode) throws Exception{
List<NameValuePair> formparams = new ArrayList<NameValuePair>
();//用于存放请求参数
for(Map.Entry<String, String> entry : params.entrySet()){
formparams.add(new BasicNameValuePair(entry.getKey(),
entry.getValue()));
}
UrlEncodedFormEntity entity = new UrlEncodedFormEntity
(formparams, encode);
HttpPost httppost = new HttpPost(path);
httppost.setEntity(entity);
HttpClient httpclient = new DefaultHttpClient();//看作是浏览器
HttpResponse response = httpclient.execute(httppost);//发送post请
求
return readStream(response.getEntity().getContent());
}
/**
* 发送请求
* @param path 请求路径
* @param params 请求参数 key为参数名称 value为参数值
* @param encode 请求参数的编码
*/
public static byte[] post(String path, Map<String, String> params, String
encode) throws Exception{
//String params = "method=save&name="+ URLEncoder.encode("老毕",
"UTF-8")+ "&age=28&";//需要发送的参数
StringBuilder parambuilder = new StringBuilder("");
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();
URL url = new URL(path);
HttpURLConnection conn = (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;
MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727;
.NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
conn.setRequestProperty("Content-Type", "application/x-www-form-
urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf
(data.length));
conn.setRequestProperty("Connection", "Keep-Alive");
//发送参数
DataOutputStream outStream = new DataOutputStream
(conn.getOutputStream());
outStream.write(data);//把参数发送出去
outStream.flush();
outStream.close();
if(conn.getResponseCode()==200){
return readStream(conn.getInputStream());
}
return null;
}
/**
* 读取流
* @param inStream
* @return 字节数组
* @throws Exception
*/
public static byte[] readStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while( (len=inStream.read(buffer)) != -1){
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
return outSteam.toByteArray();
}
}
----------------------------------------------------------------------------
5./HttpFileUpload/res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/title" />
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/title"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/timelength" />
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:numeric="integer"
android:id="@+id/timelength"
/>
<!-- android:numeric="integer",指定时长只能输入整形的数据 -->
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/filename" />
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/filename"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button"
android:onClick="save"
android:id="@+id/button"
/>
<!-- android:id="@+id/button"当点击button的时候执行这个方法 -->
</LinearLayout>
---------------------------------------------------------------------
6./HttpFileUpload/res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, NewsGetSetManagerActivity!</string>
<string name="app_name">利用getSet方法给web应用传值</string>
<string name="title">视频标题</string>
<string name="timelength">时长</string>
<string name="button">保存</string>
<string name="success">保存成功</string>
<string name="error">保存失败</string>
<string name="filename">文件名称</string>
<string name="filenoexsit">文件不存在</string>
</resources>
------------------------------------------------------------------
7./HttpFileUpload/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.credream.newmanager"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".NewsGetSetManagerActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<!--访问网络权限-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
-------------------------------------------------------------------------------
7.新建web项目:HttpFileUploadTest
/HttpFileUploadTest/src/com/credram/servlet/ManagerServlet.java
package com.credram.servlet;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
/**
* Servlet implementation class ManagerServlet
*/
public class ManagerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
String title= request.getParameter("title");
//当使用了filter就没必要再转码了:
//title=new String(title.getBytes("ISO8859-1"),"UTF-8") ;
//1.这样可以使得tomcat改变以iso8859-1的编码对接收到的数据进行解码
.以解决乱码问题
String timelength=request.getParameter("timelength");
System.out.println("视频名称:"+title);
System.out.println("时长:"+timelength);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request,
HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
//
boolean isMultipart = ServletFileUpload.isMultipartContent
(request);
if(isMultipart){
try
{
//判断类型,上传文件类型
// Create a factory for disk-based file items
FileItemFactory factory = new
DiskFileItemFactory();
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload
(factory);
String dir= request.getSession
().getServletContext().getRealPath("/files");
File dirFile=new File(dir);
if(!dirFile.exists()){
dirFile.mkdirs();//如果没有这个文件夹就
创建
}
// Parse the request
/* FileItem */
List<FileItem>
items = upload.parseRequest
(request);
for(FileItem item:items){
if (item.isFormField()) {//文本类型参数
//............
//processFormField(item);
String name = item.getFieldName();
String value = item.getString();
System.out.println(name+value+" all
data");
} else {//如果是文件类型参数,执行
//................
//processUploadedFile(item);
System.out.println(dir);
File saveFile=new File(dirFile,item.getName
());//第一个目录,第二个文件名字
item.write(saveFile);
}
}
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}else {
}
doGet(request, response);
}
}
--------------------------------------------------------------------------
2./HttpFileUploadTest/src/com/credream/filter/EncodingFilter.java
package com.credream.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class EncodingFilter implements Filter {
public void destroy() {
// 销毁的时候调用
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//每一次请求到来的时候都会调用这个方法
HttpServletRequest req=(HttpServletRequest) request;
if("GET".equals(req.getMethod())){
EncodingHttpServletRequest wrapper=new
EncodingHttpServletRequest(req);
chain.doFilter(wrapper, response);
}else {
req.setCharacterEncoding("UTF-8");
//解决乱码问题
chain.doFilter(request, response);
}
//--request请求对象--->Filter--->wrapper包装后的request对象--
>servlet-->这时候调用的request是包装后的request
}
public void init(FilterConfig fConfig) throws ServletException {
// 当web应用启动的时候就会调用这个方法
}
}
-------------------------------------------------------------------
3./HttpFileUploadTest/src/com/credream/filter/EncodingHttpServletRequest.java
package com.credream.filter;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class EncodingHttpServletRequest extends HttpServletRequestWrapper
{
private HttpServletRequest request;
public EncodingHttpServletRequest(HttpServletRequest request)
{
super(request);
this.request=request;
}
@Override
public String getParameter(String name)
{
String value=request.getParameter(name);
if(value!=null){
try
{
value=new String(value.getBytes("ISO8859-1"),"UTF-8");
} catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
}
return value;
}
}
--------------------------------------------------------------------
4./HttpFileUploadTest/WebContent/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>VideoNews</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>ListServlet</display-name>
<servlet-name>ListServlet</servlet-name>
<servlet-class>com.credram.servlet.ListServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ListServlet</servlet-name>
<url-pattern>/ListServlet</url-pattern>
</servlet-mapping>
<servlet>
<description></description>
<display-name>ManagerServlet</display-name>
<servlet-name>ManagerServlet</servlet-name>
<servlet-class>com.credram.servlet.ManagerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ManagerServlet</servlet-name>
<url-pattern>/ManagerServlet</url-pattern>
</servlet-mapping>
<filter>
<filter-name>myfilter</filter-name>
<filter-class>com.credream.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
----------------------------------------------------------------------