Android 最早使用的简单的网络请求
下面是最早从事android开发的时候写的网络请求的代码,简单高效,对于理解http请求有帮助。直接上代码,不用解释,因为非常简单。
1 import java.io.BufferedReader; 2 import java.io.DataOutputStream; 3 import java.io.FileInputStream; 4 import java.io.InputStream; 5 import java.io.InputStreamReader; 6 import java.net.HttpURLConnection; 7 import java.net.URL; 8 import java.net.URLEncoder; 9 import java.util.List; 10 import java.util.Map; 11 12 import org.apache.http.entity.mime.content.FileBody; 13 14 import android.util.Log; 15 16 public class HttpRequest { 17 18 public static final String UTF_8 = "UTF-8"; 19 20 private static String cookie = null; 21 22 23 /** 24 * GET请求 25 * 26 * @param actionUrl 27 * @param params 28 * @return 29 */ 30 public static String httpGet(String actionUrl, Map<String, String> params) { 31 try{ 32 StringBuffer urlbuff = new StringBuffer(actionUrl); 33 if (params != null && params.size() > 0) { 34 if (actionUrl.indexOf("?") >= 0) { 35 urlbuff.append("&"); 36 } else { 37 urlbuff.append("?"); 38 } 39 for (String key : params.keySet()) { 40 urlbuff.append(key).append("=").append(URLEncoder.encode(params.get(key), UTF_8)).append("&"); 41 } 42 urlbuff.deleteCharAt(urlbuff.length() - 1); 43 Log.v("---request---Get---", urlbuff.toString()); 44 } 45 URL url = new URL(urlbuff.toString()); 46 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 47 conn.setDoInput(true);// 允许输入 48 conn.setDoOutput(false);// 允许输出 49 conn.setUseCaches(false);// 不使用Cache 50 conn.setRequestMethod("GET"); 51 conn.setRequestProperty("Charset", UTF_8); 52 if (cookie != null) { 53 conn.setRequestProperty("Cookie", cookie); 54 } 55 int cah = conn.getResponseCode(); 56 if (cah != 200) 57 throw new RuntimeException("请求url失败"); 58 if (conn.getHeaderField("Set-Cookie") != null) { 59 cookie = conn.getHeaderField("Set-Cookie"); 60 } 61 Log.i("", "------------------cookie:" + cookie); 62 Map<String, List<String>> keys = conn.getHeaderFields(); 63 for(String key : keys.keySet()) { 64 List<String> list = keys.get(key); 65 for(String value : list) { 66 Log.i("", "header: key:" + key + " values:" + value); 67 } 68 } 69 70 InputStream is = conn.getInputStream(); 71 int ch; 72 StringBuilder b = new StringBuilder(); 73 while ((ch = is.read()) != -1) { 74 b.append((char) ch); 75 } 76 is.close(); 77 conn.disconnect(); 78 return b.toString(); 79 }catch(Exception e) { 80 e.printStackTrace(); 81 } 82 return null; 83 } 84 85 /** 86 * post 带文件上传 87 * @param actionUrl 88 * @param params 89 * @param files 90 * @return 91 */ 92 public static String httpPost(String actionUrl, Map<String, String> params, Map<String, FileBody> files) { 93 String LINE_START = "--"; 94 String LINE_END = "\r\n"; 95 String BOUNDRY = "*****"; 96 97 try{ 98 HttpURLConnection conn = null; 99 DataOutputStream dos = null; 100 101 int bytesRead, bytesAvailable, bufferSize; 102 long totalBytes; 103 byte[] buffer; 104 int maxBufferSize = 8096; 105 106 URL url = new URL(actionUrl); 107 conn = (HttpURLConnection) url.openConnection(); 108 109 // Allow Inputs 110 conn.setDoInput(true); 111 112 // Allow Outputs 113 conn.setDoOutput(true); 114 115 // Don't use a cached copy. 116 conn.setUseCaches(false); 117 118 // Use a post method. 119 conn.setRequestMethod("POST"); 120 //if (files != null && files.size() > 0) { 121 conn.setRequestProperty("Connection", "Keep-Alive"); 122 conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+BOUNDRY); 123 //} 124 125 Log.i("", "cookie:" + cookie); 126 if (cookie != null) { 127 conn.setRequestProperty("Cookie", cookie); 128 } 129 // // Set the cookies on the response 130 // String cookie = CookieManager.getInstance().getCookie(server); 131 // if (cookie != null) { 132 // conn.setRequestProperty("Cookie", cookie); 133 // } 134 135 // // Should set this up as an option 136 // if (chunkedMode) { 137 // conn.setChunkedStreamingMode(maxBufferSize); 138 // } 139 140 dos = new DataOutputStream(conn.getOutputStream()); 141 142 // Send any extra parameters 143 for (Object key : params.keySet()) { 144 dos.writeBytes(LINE_START + BOUNDRY + LINE_END); 145 dos.writeBytes("Content-Disposition: form-data; name=\"" + key.toString() + "\"" + LINE_END); 146 dos.writeBytes(LINE_END); 147 dos.write(params.get(key).getBytes()); 148 dos.writeBytes(LINE_END); 149 150 Log.i("", "-----key:" + key + " value:" + params.get(key)); 151 } 152 //----------- 153 if (files != null && files.size() > 0) { 154 for (String key : files.keySet()) { 155 Log.i("", "-----key:" + key + " value:" + params.get(key)); 156 FileBody fileBody = files.get(key); 157 dos.writeBytes(LINE_START + BOUNDRY + LINE_END); 158 dos.writeBytes("Content-Disposition: form-data; name=\"" + key + "\";" + " filename=\"" + fileBody.getFilename() +"\"" + LINE_END); 159 dos.writeBytes("Content-Type: " + fileBody.getMimeType() + LINE_END); 160 dos.writeBytes(LINE_END); 161 162 // Get a input stream of the file on the phone 163 InputStream fileInputStream = new FileInputStream(fileBody.getFile()); 164 bytesAvailable = fileInputStream.available(); 165 bufferSize = Math.min(bytesAvailable, maxBufferSize); 166 buffer = new byte[bufferSize]; 167 // read file and write it into form... 168 bytesRead = fileInputStream.read(buffer, 0, bufferSize); 169 totalBytes = 0; 170 while (bytesRead > 0) { 171 totalBytes += bytesRead; 172 //result.setBytesSent(totalBytes); 173 dos.write(buffer, 0, bufferSize); 174 bytesAvailable = fileInputStream.available(); 175 bufferSize = Math.min(bytesAvailable, maxBufferSize); 176 bytesRead = fileInputStream.read(buffer, 0, bufferSize); 177 } 178 dos.writeBytes(LINE_END); 179 // close streams 180 fileInputStream.close(); 181 } 182 } 183 dos.writeBytes(LINE_START + BOUNDRY + LINE_START + LINE_END); 184 dos.flush(); 185 dos.close(); 186 187 int statusCode = conn.getResponseCode(); 188 Log.i("", "---------------statusCode:" + statusCode); 189 if (statusCode != 200) { 190 throw new HttpRequestException("server error"); 191 } 192 193 //------------------ read the SERVER RESPONSE 194 InputStream is = conn.getInputStream(); 195 int ch; 196 StringBuilder b = new StringBuilder(); 197 while ((ch = is.read()) != -1) { 198 b.append((char) ch); 199 } 200 conn.disconnect(); 201 202 return b.toString(); 203 }catch(Exception e){ 204 Log.i("", "---------------" + e.getMessage(), e.fillInStackTrace()); 205 e.printStackTrace(); 206 } 207 return null; 208 } 209 210 /** 211 * post请求 212 * @param actionUrl 213 * @param params 214 * @return 215 */ 216 public static String httpPost(String actionUrl, Map<String, String> params){ 217 try{ 218 URL url = new URL(actionUrl); 219 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 220 //因为这个是post请求,设立需要设置为true 221 conn.setDoOutput(true); 222 conn.setDoInput(true); 223 // 设置以POST方式 224 conn.setRequestMethod("POST"); 225 // Post 请求不能使用缓存 226 conn.setUseCaches(false); 227 conn.setInstanceFollowRedirects(true); 228 // 配置本次连接的Content-type,配置为application/x-www-form-urlencoded的 229 conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 230 // 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成, 231 // 要注意的是connection.getOutputStream会隐含的进行connect。 232 if (cookie != null) { 233 conn.setRequestProperty("Cookie", cookie); 234 } 235 conn.connect(); 236 //DataOutputStream流 237 DataOutputStream out = new DataOutputStream(conn.getOutputStream()); 238 //要上传的参数 239 StringBuffer content = new StringBuffer(); 240 for (String key : params.keySet()) { 241 //String content = "par=" + URLEncoder.encode("ABCDEFG", "gb2312"); 242 content.append(key).append("=").append(params.get(key)).append("&"); 243 } 244 //将要上传的内容写入流中 245 out.writeBytes(content.toString()); 246 //刷新、关闭 247 out.flush(); 248 out.close(); 249 250 int statusCode = conn.getResponseCode(); 251 Log.i("", "---------------statusCode:" + statusCode); 252 if (statusCode != 200) { 253 throw new HttpRequestException("server error"); 254 } 255 if (conn.getHeaderField("Set-Cookie") != null) { 256 cookie = conn.getHeaderField("Set-Cookie"); 257 } 258 //获取数据 259 InputStream is = conn.getInputStream(); 260 int ch; 261 StringBuilder b = new StringBuilder(); 262 while ((ch = is.read()) != -1) { 263 b.append((char) ch); 264 } 265 conn.disconnect(); 266 return b.toString(); 267 }catch(Exception e) { 268 Log.i("", "---------------" + e.getMessage(), e.fillInStackTrace()); 269 e.printStackTrace(); 270 } 271 return null; 272 } 273 274 }
1. application/x-www-form-urlencoded
最常见的 POST
提交数据的方式了。浏览器的原生 form 表单,如果不设置 enctype
属性,那么最终就会以 application/x-www-form-urlencoded
方式提交数据。
传递的key/val会经过URL转码,所以如果传递的参数存在中文或者特殊字符需要注意。
1 //例子 2 //b=曹,a=1 3 4 POST HTTP/1.1(CRLF) 5 Host: www.example.com(CRLF) 6 Content-Type: application/x-www-form-urlencoded(CRLF) 7 Cache-Control: no-cache(CRLF) 8 (CRLF) 9 b=%E6%9B%B9&a=1(CRLF) 10 //这里b参数的值"曹"因为URL转码变成其他的字符串了
2. text/xml
1 //例子 2 3 POST http://www.example.com HTTP/1.1(CRLF) 4 Content-Type: text/xml(CRLF) 5 (CRLF) 6 <?xml version="1.0"?> 7 <resource> 8 <id>123</id> 9 <params> 10 <name> 11 <value>homeway</value> 12 </name> 13 <age> 14 <value>22</value> 15 </age> 16 </params> 17 </resource>
3.application/json
1 //例子 2 //传递json 3 4 POST HTTP/1.1(CRLF) 5 Host: www.example.com(CRLF) 6 Content-Type: application/json(CRLF) 7 Cache-Control: no-cache(CRLF) 8 Content-Length: 24(CRLF) 9 (CRLF) 10 { 11 "a":1, 12 "b":"hello" 13 }
4. multipart/form-data
使用表单上传文件时,必须让 form
的 enctyped
等于这个值。
并且Http协议会使用boundary来分割上传的参数
1 //例子 2 //a="曹",file1是一个文件 3 4 POST HTTP/1.1(CRLF) 5 Host: www.example.com(CRLF) 6 //注意data;和boundary之间有一个空格,并且----WebKitFormBoundary7MA4YWxkTrZu0gW是可以自定义的 7 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW(CRLF) 8 Cache-Control: no-cache(CRLF) 9 Content-Length: 728 10 (CRLF) 11 //如果有Content-Length的话,则Content-Length指下面所有的字节总数,包括boundary 12 //这里用自定义的boundary来进行分割,注意会在头部加多"--" 13 ------WebKitFormBoundary7MA4YWxkTrZu0gW(CRLF) 14 Content-Disposition: form-data; name="a"(CRLF) 15 (CRLF) 16 曹(CRLF) 17 ------WebKitFormBoundary7MA4YWxkTrZu0gW(CRLF) 18 Content-Disposition: form-data; name="file1"; filename="1.jpg" 19 Content-Type: application/octet-stream(CRLF) 20 (CRLF) 21 //此处是参数file1 对应的文件的二进制数据 22 [654dfasalk;af&6…](CRLF) 23 //最后一个boundary会分别在头部和尾部加多"--" 24 ------WebKitFormBoundary7MA4YWxkTrZu0gW--(CRLF)
//多个文件同时上传
1 POST HTTP/1.1(CRLF) 2 Host: www.example.com(CRLF) 3 //注意data;和boundary之间有一个空格,并且----WebKitFormBoundary7MA4YWxkTrZu0gW是可以自定义的 4 Content-Type: multipart/form-data; boundary=---------------------------418888951815204591197893077 5 Cache-Control: no-cache(CRLF) 6 Content-Length: 12138(CRLF) 7 (CRLF) 8 -----------------------------418888951815204591197893077(CRLF) 9 // 文件1的头部boundary 10 Content-Disposition: form-data; name="userfile[]"; filename="文件1.md"(CRLF) 11 Content-Type: text/markdown(CRLF) 12 (CRLF) 13 // 文件1内容开始 14 // ... 15 // 文件1内容结束 16 -----------------------------418888951815204591197893077(CRLF) 17 // 文件2的头部boundary 18 Content-Disposition: form-data; name="userfile[]"; filename="文件2"(CRLF) 19 Content-Type: application/octet-stream(CRLF) 20 (CRLF) 21 // 文件2内容开始 22 // ... 23 // 文件2内容结束 24 -----------------------------418888951815204591197893077(CRLF) 25 // 文件3的头部boundary 26 Content-Disposition: form-data; name="userfile[]"; filename="文件3"(CRLF) 27 Content-Type: application/octet-stream(CRLF) 28 (CRLF) 29 // 文件3内容开始 30 // ... 31 // 文件3内容结束 32 -----------------------------418888951815204591197893077(CRLF) 33 // 参数username的头部boundary 34 Content-Disposition: form-data; name="username"(CRLF) 35 (CRLF) 36 zhangsan 37 -----------------------------418888951815204591197893077(CRLF) 38 // 参数password的头部boundary 39 Content-Disposition: form-data; name="password"(CRLF) 40 (CRLF) 41 zhangxx 42 -----------------------------418888951815204591197893077-- 43 // 尾部boundary,表示结束
注意 :(CRLF)
指\r\n