在做嘀咕客户端的时候,要实现拍照上传的功能。根据嘀咕api提供的接口,文档看上去很复杂,我用一个简单html文件来说明问题。
几个关键点:
这个表单使用post方法
有几个文本域,还用到file域,即文件上传
编码用utf-8
接下来,我在android中使用HttpURLConnection来构建一个符合这些规则的表单Post到服务器。
到底这个表单是怎么样的一种结构,它肯定是要根据http传输协议来构造出来的。我介绍一种非常直观的方法。利用FireFox的FireBug插件,我们在这个html表单上点击提交时候,可以看到这个请求到底是怎么样的。
明白了要做什么事情,接下来就是用java代码来构建这样的StringBuffer了。
下面给出代码
/**
* 上传附件 (拍照)
* @param bitmap 待上传的Bitmap图
* @param fileKey 表单变量名
* @param urlstr 上传地址
* @param hmap 参数
* @param ctx context
* @return
*/
public static String postFileFromBitmap2(String urlstr, HashMap<String, String> hmap) {
dout("postURLContent:" + urlstr);
String fileKey = "image0";
String rs = "";
String temp = "temp.jpg";
Bitmap2File(bitmap, temp, U.ctx_for_getResString);
String exsistingFileName = U.ctx_for_getResString.getFilesDir() + "/" + temp;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "---------------------------11538186919912";
try {
File f = new File(exsistingFileName);
FileInputStream fileInputStream = new FileInputStream(f);
if (!f.exists())
return rs;
URL url = new URL(urlstr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
//兼容嘀咕的用户账户密码信息必须通过 AUTH_HTTP 方式提供
if(hmap.containsKey("AUTH_HTTP_ENCODING")){
conn.setRequestProperty("Authorization", "Basic " + hmap.get("AUTH_HTTP_ENCODING"));
}
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"content\""+ lineEnd);
dos.writeBytes(lineEnd + URLEncoder.encode(""+hmap.get("content"), "UTF-8")+ lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"source\""+ lineEnd);
dos.writeBytes(lineEnd + URLEncoder.encode(""+hmap.get("source"), "UTF-8")+ lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"uploadImg\""+ lineEnd);
dos.writeBytes(lineEnd + URLEncoder.encode("xiexiezhichi", "UTF-8")+ lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"" + fileKey + "\";filename=\"" + exsistingFileName+ "\"" + lineEnd);
dos.writeBytes("Content-Type: image/jpeg"+lineEnd);
dos.writeBytes(lineEnd);
int bytesAvailable = fileInputStream.available();
byte[] buffer = new byte[bytesAvailable];
int bytesRead = fileInputStream.read(buffer, 0, bytesAvailable);
while (bytesRead > 0) {
dos.write(buffer, 0, bytesAvailable);
bytesAvailable = fileInputStream.available();
bytesRead = fileInputStream.read(buffer, 0, bytesAvailable);
}
dos.writeBytes(lineEnd);
dos.writeBytes(boundary + lineEnd);
fileInputStream.close();
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"image1\";filename=\"\"" + lineEnd);
dos.writeBytes("Content-Type: application/octet-stream"+lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"image2\";filename=\"\"" + lineEnd);
dos.writeBytes("Content-Type: application/octet-stream"+lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
dos.flush();
dos.close();
InputStream in = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
StringBuffer sb2 = new StringBuffer();
String tmp = null;
while ((tmp = br.readLine()) != null) {
sb2.append(tmp);
}
br.close();
in.close();
return sb2.toString();
} catch (IOException e) {
e.printStackTrace();
}
return rs;
}