今天学习了android文件上传,在网上查找资料发现篇不错的博文
http://blog.csdn.net/lmj623565791/article/details/23781773
之前做web开发,前台要传文件到后台需要在form中写multipart/form-data,然后form submit下剩余的工作就交给浏览器来完成了。
现在用android做文件上传的话,我的思路是模仿网页中的form submit 到后台。
查看web项目中文件上传页面的控制台显示情况:
request headers中几个重要的字段:
content-type是必须的,multipart/form-data说明我们要传递的是文件而不是字符串它包括一个类似标志性质的名为boundary的标志,
它可以是随便输入的字符串(对后面的具体内容也是必须的,它用来分辨一段内容的开始)。
Content-Length: 3693 ,这里的3693是要上传文件的总长度。(实测发现程序会自动设置)
request payload部分:
1)如果你是要上传一些普通参数:
第一句:--(分隔符)----WebKitFormBoundary2iQVifY9CMxltBFm(标识符boundary) \r\n (回车换行,没有这个回车换行就实现不了上传功能)
第二句:Content-Disposition: form-data; name ="id"(说明要声明表单字段id) \r\n (回车换行,没有这个回车换行就实现不了上传功能)
第三句:\r\n (回车换行,没有这个回车换行就实现不了上传功能)
第四句:8aa1034d50114b240150125f4ae200dc(表单字段id对应的值)\r\n (回车换行,没有这个回车换行就实现不了上传功能)
2)上传文件:
第一句:--(分隔符)----WebKitFormBoundary2iQVifY9CMxltBFm(标识符boundary) \r\n (回车换行,没有这个回车换行就实现不了上传功能)
第二句:Content-Disposition: form-data; name ="uploadFile"(说明要声明表单字段id,后台就是通过这个字符串获取文件对象的);filename="00000.jpg"(文件名) \r\n (回车换行,没有这个回车换行就实现不了上传功能)
第三句:Content-Type:application/octet-stream;charset=utf-8(与上面的截图不同,我android端用的是这句话,到底这行应该怎么写我没研究过)\r\n
第四句:\r\n (回车换行,没有这个回车换行就实现不了上传功能)
第五句:(这一行应该是要显示文件的值的,但我们看到的是空的,可能因为文件不能像字符串一样显示出来的原因吧,不过真实情况应该是文件的字节码)\r\n
第六句:--(分隔符)----WebKitFormBoundary2iQVifY9CMxltBFm(标识符boundary)--(request payload 部分结束句)
具体代码
package com.example.filemanagerdemo;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.Map;
import java.util.UUID;
public class HTTPUtil {
static final String CHARSET = "utf-8"; // 设置编码
static final int TIME_OUT = 10 * 10000000; // 超时时间
static final String ENCORDING="UTF-8";
static final String END = "\r\n";
static final String HYPHENS = "--";
static final String CONTENT_TYPE = "multipart/form-data"; // 内容类型
static final String BOUNDARY = UUID.randomUUID().toString();
static final String UPLOADFileFIELD = "uploadFile";
public static InputStream uploadFile(String remote_url,Map<String,Object> params,Map<String, File> files,String upload_file_field) throws IOException{
HttpURLConnection con = HTTPUtil.getHttpURLConnection(remote_url);
/*******************************************************************************************************/
/*******************************************************************************************************/
con.setRequestProperty("content-Type",CONTENT_TYPE+"; boundary=" + BOUNDARY);
/* 设定DataOutputStream */
DataOutputStream ds = new DataOutputStream(con.getOutputStream());
StringBuffer requestFormBody = new StringBuffer("");
if(params!=null&¶ms.size()>0){
for(String field:params.keySet()){
requestFormBody.append(HYPHENS + BOUNDARY + END);
requestFormBody.append("Content-Disposition: form-data; name=\""+field+"\"" + END);
requestFormBody.append(END);
requestFormBody.append(String.valueOf(params.get(field)) + END);
}
}
ds.writeBytes(requestFormBody.toString());
if(files!=null&&files.size()>0){
for(String field:files.keySet()){
File file = files.get(field);
if(file!=null){
requestFormBody = new StringBuffer();
requestFormBody.append(HYPHENS + BOUNDARY + END);
/**
* 这里重点注意: name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件
* filename是文件的名字,包含后缀名的 比如:abc.png
*/
requestFormBody.append("Content-Disposition: form-data; name=\""+UPLOADFileFIELD+"\"; filename=\"" + file.getName() + "\"" + END);
requestFormBody.append("Content-Type: application/octet-stream; charset=" + CHARSET + END);
requestFormBody.append(END);
ds.writeBytes(requestFormBody.toString());
/* 取得文件的FileInputStream */
FileInputStream fStream = new FileInputStream(file);
/* 设定每次写入1024bytes */
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int length = -1;
/* 从文件读取数据到缓冲区 */
while ((length = fStream.read(buffer)) != -1)
{
/* 将数据写入DataOutputStream中 */
ds.write(buffer, 0, length);
}
ds.writeBytes(END);
fStream.close();
}
}
}
ds.writeBytes(HYPHENS + BOUNDARY + HYPHENS + END );
ds.close();
return con.getInputStream();
}
public static HttpURLConnection getHttpURLConnection(String remote_url){
HttpURLConnection con = null;
try {
URL url = new URL(remote_url);
con = (HttpURLConnection) url.openConnection();
con.setReadTimeout(TIME_OUT);
con.setConnectTimeout(TIME_OUT);
/* 允许Input、Output,不使用Cache */
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
/* 设定传送的method=POST */
con.setRequestMethod("POST");
/* setRequestProperty */
con.setRequestProperty("Charset", ENCORDING);
con.setRequestProperty("connection", "keep-alive");
} catch (MalformedURLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (ProtocolException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return con;
}
}
如何调用
remote_url 文件上传地址
params 普通表单参数 域名=>值
files 文件
UPLOADFILEFIELD 文件的域名(就算是多文件,后台也是根据这个字段接收的,结果自然是List)
/* 取得Response内容 */
InputStream is = HTTPUtil.uploadFile(remote_url, params, files, UPLOADFILEFIELD);
int ch;
StringBuffer b = new StringBuffer();
while ((ch = is.read()) != -1)
{
b.append((char) ch);
}
return b;
服务器端代码很简单不上了。
文件上传完成。