Android 发送HTTP GET POST 请求以及通过 MultipartEntityBuilder 上传文件第二版
上次粗略的写了相同功能的代码,这次整理修复了之前的一些BUG,结构也大量修改过了,现在应用更加方便点
http://blog.csdn.net/zhouzme/article/details/18940279
直接上代码了:
ZHttpRequset.java
package com.ai9475.util; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.protocol.HTTP; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; /** * Created by ZHOUZ on 14-2-3. */ public class ZHttpRequest { public final String HTTP_GET = "GET"; public final String HTTP_POST = "POST"; /** * 当前请求的 URL */ protected String url = ""; /** * HTTP 请求的类型 */ protected String requsetType = HTTP_GET; /** * 连接请求的超时时间 */ protected int connectionTimeout = 5000; /** * 读取远程数据的超时时间 */ protected int soTimeout = 10000; /** * 服务端返回的状态码 */ protected int statusCode = -1; /** * 当前链接的字符编码 */ protected String charset = HTTP.UTF_8; /** * HTTP GET 请求管理器 */ protected HttpRequestBase httpRequest= null; /** * HTTP 请求的配置参数 */ protected HttpParams httpParameters= null; /** * HTTP 请求响应 */ protected HttpResponse httpResponse= null; /** * HTTP 客户端连接管理器 */ protected HttpClient httpClient= null; /** * HTTP POST 方式发送多段数据管理器 */ protected MultipartEntityBuilder multipartEntityBuilder= null; /** * 绑定 HTTP 请求的事件监听器 */ protected OnHttpRequestListener onHttpRequestListener = null; public ZHttpRequest(){} public ZHttpRequest(OnHttpRequestListener listener) { this.setOnHttpRequestListener(listener); } /** * 设置当前请求的链接 * * @param url * @return */ public ZHttpRequest setUrl(String url) { this.url = url; return this; } /** * 设置连接超时时间 * * @param timeout 单位(毫秒),默认 5000 * @return */ public ZHttpRequest setConnectionTimeout(int timeout) { this.connectionTimeout = timeout; return this; } /** * 设置 socket 读取超时时间 * * @param timeout 单位(毫秒),默认 10000 * @return */ public ZHttpRequest setSoTimeout(int timeout) { this.soTimeout = timeout; return this; } /** * 设置获取内容的编码格式 * * @param charset 默认为 UTF-8 * @return */ public ZHttpRequest setCharset(String charset) { this.charset = charset; return this; } /** * 获取当前 HTTP 请求的类型 * * @return */ public String getRequestType() { return this.requsetType; } /** * 判断当前是否 HTTP GET 请求 * * @return */ public boolean isGet() { return this.requsetType == HTTP_GET; } /** * 判断当前是否 HTTP POST 请求 * * @return */ public boolean isPost() { return this.requsetType == HTTP_POST; } /** * 获取 HTTP 请求响应信息 * * @return */ public HttpResponse getHttpResponse() { return this.httpResponse; } /** * 获取 HTTP 客户端连接管理器 * * @return */ public HttpClient getHttpClient() { return this.httpClient; } /** * 添加一条 HTTP 请求的 header 信息 * * @param name * @param value * @return */ public ZHttpRequest addHeader(String name, String value) { this.httpRequest.addHeader(name, value); return this; } /** * 获取 HTTP GET 控制器 * * @return */ public HttpGet getHttpGet() { return (HttpGet) this.httpRequest; } /** * 获取 HTTP POST 控制器 * * @return */ public HttpPost getHttpPost() { return (HttpPost) this.httpRequest; } /** * 获取请求的状态码 * * @return */ public int getStatusCode() { return this.statusCode; } /** * 通过 GET 方式请求数据 * * @param url * @return * @throws IOException */ public String get(String url) throws Exception { this.requsetType = HTTP_GET; // 设置当前请求的链接 this.setUrl(url); // 新建 HTTP GET 请求 this.httpRequest = new HttpGet(this.url); // 执行客户端请求 this.httpClientExecute(); // 监听服务端响应事件并返回服务端内容 return this.checkStatus(); } /** * 获取 HTTP POST 多段数据提交管理器 * * @return */ public MultipartEntityBuilder getMultipartEntityBuilder() { if (this.multipartEntityBuilder == null) { this.multipartEntityBuilder = MultipartEntityBuilder.create(); // 设置为浏览器兼容模式 multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); // 设置请求的编码格式 multipartEntityBuilder.setCharset(Charset.forName(this.charset)); } return this.multipartEntityBuilder; } /** * 配置完要 POST 提交的数据后, 执行该方法生成数据实体等待发送 */ public void buildPostEntity() { // 生成 HTTP POST 实体 HttpEntity httpEntity = this.multipartEntityBuilder.build(); this.getHttpPost().setEntity(httpEntity); } /** * 发送 POST 请求 * * @param url * @return * @throws Exception */ public String post(String url) throws Exception { this.requsetType = HTTP_POST; // 设置当前请求的链接 this.setUrl(url); // 新建 HTTP POST 请求 this.httpRequest = new HttpPost(this.url); // 执行客户端请求 this.httpClientExecute(); // 监听服务端响应事件并返回服务端内容 return this.checkStatus(); } /** * 执行 HTTP 请求 * * @throws Exception */ protected void httpClientExecute() throws Exception { // 配置 HTTP 请求参数 this.httpParameters = new BasicHttpParams(); this.httpParameters.setParameter("charset", this.charset); // 设置 连接请求超时时间 HttpConnectionParams.setConnectionTimeout(this.httpParameters, this.connectionTimeout); // 设置 socket 读取超时时间 HttpConnectionParams.setSoTimeout(this.httpParameters, this.soTimeout); // 开启一个客户端 HTTP 请求 this.httpClient = new DefaultHttpClient(this.httpParameters); // 启动 HTTP POST 请求执行前的事件监听回调操作(如: 自定义提交的数据字段或上传的文件等) this.getOnHttpRequestListener().onRequest(this); // 发送 HTTP 请求并获取服务端响应状态 this.httpResponse = this.httpClient.execute(this.httpRequest); // 获取请求返回的状态码 this.statusCode = this.httpResponse.getStatusLine().getStatusCode(); } /** * 读取服务端返回的输入流并转换成字符串返回 * * @throws Exception */ public String getInputStream() throws Exception { // 接收远程输入流 InputStream inStream = this.httpResponse.getEntity().getContent(); // 分段读取输入流数据 ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; int len = -1; while ((len = inStream.read(buf)) != -1) { baos.write(buf, 0, len); } // 数据接收完毕退出 inStream.close(); // 将数据转换为字符串保存 return new String(baos.toByteArray(), this.charset); } /** * 关闭连接管理器释放资源 */ protected void shutdownHttpClient() { if (this.httpClient != null && this.httpClient.getConnectionManager() != null) { this.httpClient.getConnectionManager().shutdown(); } } /** * 监听服务端响应事件并返回服务端内容 * * @return * @throws Exception */ protected String checkStatus() throws Exception { OnHttpRequestListener listener = this.getOnHttpRequestListener(); String content; if (this.statusCode == HttpStatus.SC_OK) { // 请求成功, 回调监听事件 content = listener.onSucceed(this.statusCode, this); } else { // 请求失败或其他, 回调监听事件 content = listener.onFailed(this.statusCode, this); } // 关闭连接管理器释放资源 this.shutdownHttpClient(); return content; } /** * HTTP 请求操作时的事件监听接口 */ public interface OnHttpRequestListener { /** * 初始化 HTTP GET 或 POST 请求之前的 header 信息配置 或 其他数据配置等操作 * * @param request * @throws Exception */ public void onRequest(ZHttpRequest request) throws Exception; /** * 当 HTTP 请求响应成功时的回调方法 * * @param statusCode 当前状态码 * @param request * @return 返回请求获得的字符串内容 * @throws Exception */ public String onSucceed(int statusCode, ZHttpRequest request) throws Exception; /** * 当 HTTP 请求响应失败时的回调方法 * * @param statusCode 当前状态码 * @param request * @return 返回请求失败的提示内容 * @throws Exception */ public String onFailed(int statusCode, ZHttpRequest request) throws Exception; } /** * 绑定 HTTP 请求的监听事件 * * @param listener * @return */ public ZHttpRequest setOnHttpRequestListener(OnHttpRequestListener listener) { this.onHttpRequestListener = listener; return this; } /** * 获取已绑定过的 HTTP 请求监听事件 * * @return */ public OnHttpRequestListener getOnHttpRequestListener() { return this.onHttpRequestListener; } }
在 Activity 中的使用方法(这里我还是只写主体部分代码):
MainActivity.java
public void doClick(View view) { ZHttpRequest get = new ZHttpRequest(); get .setCharset(HTTP.UTF_8) .setConnectionTimeout(5000) .setSoTimeout(5000); get.setOnHttpRequestListener(new ZHttpRequest.OnHttpRequestListener() { @Override public void onRequest(ZHttpRequest request) throws Exception { } @Override public String onSucceed(int statusCode, ZHttpRequest request) throws Exception { return request.getInputStream(); } @Override public String onFailed(int statusCode, ZHttpRequest request) throws Exception { return "GET 请求失败:statusCode "+ statusCode; } }); ZHttpRequest post = new ZHttpRequest(); post .setCharset(HTTP.UTF_8) .setConnectionTimeout(5000) .setSoTimeout(10000); post.setOnHttpRequestListener(new ZHttpRequest.OnHttpRequestListener() { private String CHARSET = HTTP.UTF_8; private ContentType TEXT_PLAIN = ContentType.create("text/plain", Charset.forName(CHARSET)); @Override public void onRequest(ZHttpRequest request) throws Exception { // 设置发送请求的 header 信息 request.addHeader("cookie", "abc=123;456=爱就是幸福;"); // 配置要 POST 的数据 MultipartEntityBuilder builder = request.getMultipartEntityBuilder(); builder.addTextBody("p1", "abc"); builder.addTextBody("p2", "中文", TEXT_PLAIN); builder.addTextBody("p3", "abc中文cba", TEXT_PLAIN); if (picPath != null && ! "".equals(picPath)) { builder.addTextBody("pic", picPath); builder.addBinaryBody("file", new File(picPath)); } request.buildPostEntity(); } @Override public String onSucceed(int statusCode, ZHttpRequest request) throws Exception { return request.getInputStream(); } @Override public String onFailed(int statusCode, ZHttpRequest request) throws Exception { return "POST 请求失败:statusCode "+ statusCode; } }); TextView textView = (TextView) findViewById(R.id.showContent); String content = "初始内容"; try { if (view.getId() == R.id.doGet) { content = get.get("http://www.baidu.com"); content = "GET数据:isGet: " + (get.isGet() ? "yes" : "no") + " =>" + content; } else { content = post.post("http://192.168.1.6/test.php"); content = "POST数据:isPost" + (post.isPost() ? "yes" : "no") + " =>" + content; } } catch (IOException e) { content = "IO异常:" + e.getMessage(); } catch (Exception e) { content = "异常:" + e.getMessage(); } textView.setText(content); }
其中 picPath 为 SD 卡中的图片路径 String 类型,我是直接拍照后进行上传用的
关于拍照显示并上传的代码部分:http://blog.csdn.net/zhouzme/article/details/18952201
布局页面
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ScrollView android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/doGet" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dp" android:layout_marginBottom="10dp" android:text="GET请求" android:onClick="doClick" /> <Button android:id="@+id/doPost" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dp" android:layout_marginBottom="10dp" android:text="POST请求" android:onClick="doClick" /> <Button android:id="@+id/doPhoto" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dp" android:layout_marginBottom="10dp" android:text="拍照" android:onClick="doPhoto" /> <TextView android:id="@+id/showContent" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" /> <ImageView android:id="@+id/showPhoto" android:layout_width="fill_parent" android:layout_height="250dp" android:scaleType="centerCrop" android:src="@drawable/add" android:layout_marginBottom="10dp" /> </LinearLayout> </ScrollView> </LinearLayout>
至于服务端我用的 PHP ,只是简单的输出获取到的数据而已
<?php echo 'GET:<br>'. "\n"; //print_r(array_map('urldecode', $_GET)); print_r($_GET); echo '<br>'. "\n". 'POST:<br>'. "\n"; //print_r(array_map('urldecode', $_POST)); print_r($_POST); echo '<br>'. "\n". 'FILES:<br>'. "\n"; print_r($_FILES); echo '<br>'. "\n". 'COOKIES:<br>'. "\n"; print_r($_COOKIE);