下面是最早从事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 .HttpURLConnection;
7 import .URL;
8 import .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="文件"(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