本类可以实现在安卓开发中在一个表单中同时提交参数、数据和上传多个文件,并可以自行制定字段名称。直接上代码:
package com.example.myuploadtest.utils; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.List; import java.util.Map; import java.util.UUID; import com.example.myuploadtest.Log;//这行可以删了替换为系统自带的 public class HttpConnectionUtil { private static final String TAG = HttpConnectionUtil.class.getSimpleName(); private static final int TIME_OUT = 10*10000000; //超时时间 private static final String CHARSET = "utf-8"; //设置编码 private static final String PREFIX = "--"; //前缀 private static final String LINE_END = "\r\n"; //换行 private static final String BOUNDARY = UUID.randomUUID().toString(); //边界标识 随机生成 private static final String CONTENT_TYPE = "multipart/form-data"; //内容类型 public static void postRequest(String strUrl, Map<String, String> strParams, Map<String, File> fileParams, FileUploadListener listener){ String strResult = null; HttpURLConnection conn = null; try { URL url = new URL(strUrl); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); //请求方式 conn.setReadTimeout(TIME_OUT); conn.setConnectTimeout(TIME_OUT); conn.setDoInput(true); //允许输入流 conn.setDoOutput(true); //允许输出流 conn.setUseCaches(false); //Post 请求不能使用缓存 //设置请求头参数 conn.setRequestProperty("Charset", CHARSET);//设置编码 conn.setRequestProperty("connection", "keep-alive"); conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY); //请求体 //提交参数 DataOutputStream dos = new DataOutputStream(conn.getOutputStream()); dos.writeBytes( getStrParams(strParams).toString() ); dos.flush(); //当文件不为空,把文件包装并且上传 if(fileParams.size() > 0) { //文件上传 postFileParams(dos, fileParams, listener); } //请求结束标志 dos.writeBytes(PREFIX + BOUNDARY + PREFIX + LINE_END); dos.flush(); dos.close(); Log.i(TAG, "postResponseCode() = "+conn.getResponseCode() ); //获取服务器响应码 200=成功, 当服务器响应成功,获取服务器响应的流 if (conn.getResponseCode() == 200) { InputStream in = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String line = null; StringBuilder response = new StringBuilder(); while ((line = reader.readLine()) != null) { response.append(line); } Log.i(TAG, "run: " + response); strResult = response.toString(); } else{ Log.i(TAG, "postResponseCode() = "+conn.getResponseCode() ); strResult = null; } listener.onFinish(conn.getResponseCode(), strResult, conn.getHeaderFields()); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if (conn!=null){ conn.disconnect(); } } //return strResult; } public interface FileUploadListener{ public void onProgress(long pro, double precent); public void onFinish(int code, String res, Map<String, List<String>> headers); } /** * 对post参数进行拼接编码处理,返回拼接后的结果 */ private static StringBuilder getStrParams(Map<String,String> strParams){ StringBuilder strSb = new StringBuilder(); for (Map.Entry<String, String> entry : strParams.entrySet() ){ strSb.append(PREFIX) .append(BOUNDARY) .append(LINE_END) .append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINE_END) .append("Content-Type: text/plain; charset=" + CHARSET + LINE_END) .append("Content-Transfer-Encoding: 8bit" + LINE_END) .append(LINE_END)// 参数头设置完以后需要两个换行,然后才是参数内容 .append(entry.getValue()) .append(LINE_END); } return strSb; } /** * 对post文件进行拼接编码处理,直接上传 */ private static void postFileParams(DataOutputStream dos, Map<String, File> fileParams, FileUploadListener listener){ StringBuilder fileSb = new StringBuilder(); for (Map.Entry<String, File> fileEntry: fileParams.entrySet()){ //写入文件参数 fileSb.append(PREFIX) .append(BOUNDARY) .append(LINE_END) /** * 这里重点注意: name里面的值为服务端需要的key 只有这个key 才可以得到对应的文件 * filename是文件的名字,包含后缀名的 比如:abc.png */ .append("Content-Disposition: form-data; name=\""+ fileEntry.getKey() + "\"; filename=\"" + fileEntry.getValue().getName() + "\"" + LINE_END) .append("Content-Type: application/octet-stream; charset=" + CHARSET + LINE_END) //此处的ContentType不同于 请求头 中Content-Type .append("Content-Transfer-Encoding: 8bit" + LINE_END) .append(LINE_END);// 参数头设置完以后需要两个换行,然后才是参数内容 //写入文件数据 try { dos.writeBytes(fileSb.toString()); dos.flush(); InputStream is = new FileInputStream(fileEntry.getValue()); byte[] buffer = new byte[1024]; long totalbytes = fileEntry.getValue().length(); long curbytes = 0; Log.i("cky","total="+totalbytes); int len = 0; while ((len = is.read(buffer)) != -1){ dos.write(buffer,0,len); curbytes += len; listener.onProgress(curbytes, 1.0d*curbytes/totalbytes); } is.close(); dos.writeBytes(LINE_END); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
使用方式如下:
final String strUrl = "http://127.0.0.1/post/"; final HashMap<String,String> strParams = new HashMap<String,String>(); strParams.put("action", "uploadByAJAX"); strParams.put("imei", "A00123"); final HashMap<String,File> fileParams = new HashMap<String,File>(); fileParams.put("file", new File(picturePath)); //fileParams.put("file", new File(selectedImage.toString())); new Thread(){ @Override public void run() { HttpConnectionUtil.postRequest(strUrl, strParams, fileParams, new FileUploadListener() { @Override public void onProgress(long pro, double precent) { Log.i("cky", precent+""); } @Override public void onFinish(int code, String res, Map<String, List<String>> headers) { Log.i("cky", res); } }); } }.start();
主要参考了如下链接:
https://blog.csdn.net/crazy__chen/article/details/47703781