微信支付开发教程JAVA编[004]-使用HttpClient详解

来源:互联网 发布:众里寻她千百最新域名 编辑:程序博客网 时间:2024/04/30 23:41

        我承接app微信公众号开发,如果有谁需要的话,可以惠顾我,谢谢.

QQ: 40678884

微信: szuzsq

主页: http://www.wxshaker.com

博客: http://blog.csdn.net/szuzsq

-------------------------------------------------------------------------------------------------------------------------------------



        需要注意的是,HttpClient并不是基本的java库(android下就有).
http://hc.apache.org/downloads.cgi
我下载的是
http://mirrors.tuna.tsinghua.edu.cn/apache/httpcomponents/httpclient/binary/httpcomponents-client-4.5.3-bin.zip
下载后,会有很多jar,大家可以酌情添加到工程,我就只添加了commons-codec-1.9.jar,commons-logging-1.2.jar,httpmime-4.5.3.jar,httpcore-4.4.6.jar,httpclient-4.5.3.jar

        HttpClient网上例子比较多,我直接附上调试好了的代码:

/*************************************************************** * http,https访问的站点 ***************************************************************/package wxlib.wxsdk.lib.utils;import java.io.File;import java.io.FileOutputStream;import java.io.OutputStream;import java.util.Map;import org.apache.http.HttpEntity;import org.apache.http.client.config.RequestConfig;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.ByteArrayEntity;import org.apache.http.entity.ContentType;import org.apache.http.entity.StringEntity;import org.apache.http.entity.mime.HttpMultipartMode;import org.apache.http.entity.mime.MultipartEntityBuilder;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.util.EntityUtils;import org.json.JSONObject;public class HttpRequest {/** * @tutorial 支持http,https * @param string $url 要访问的站点 * @param array,object $data get只能是key/value的参数集合 * @param int $timeout 超时时间,单位秒 * @return 站点数据或失败信息 */static public Object get(String url, Object data/* = null*/, int timeout/* = 30*/) {//将data转化为url参数:par1=val1&par2=va2&par3=val3String param = "";if(data != null && !data.equals("") && data instanceof Map) {@SuppressWarnings("unchecked")Map<String, Object> map = (Map<String, Object>)data;for(Map.Entry<String, Object> entry : map.entrySet()) {String key = entry.getKey() != null ? entry.getKey().toString() : "";String val = entry.getValue() != null ? entry.getValue().toString() : "";if(key.equals(""))continue;param += key + "=" + val + "&";}}if(data != null && !data.equals("") && data instanceof JSONObject) {JSONObject map = (JSONObject)data;for(String key : map.keySet()) {if(key == null || key.equals(""))continue;String val = map.optString(key);if(val == null)continue;param += key + "=" + val + "&";}}if(param.endsWith("&"))param = param.substring(0, param.length() - 1);if(!param.equals(""))url += ((url.indexOf("?") != -1) ? "&" : "?") + param;String result = "";//创建http请求(post方式)HttpGet httpGet = new HttpGet(url);httpGet.addHeader("Content-Type", "text/html; charset=UTF-8");//得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别//StringEntity stringEntity = new StringEntity(data.toString(), "UTF-8");//httpGet.setEntity(stringEntity);//设置请求器配置:如超时限制等RequestConfig config = RequestConfig.custom().setSocketTimeout(timeout * 1000).setConnectTimeout(timeout * 1000).build();httpGet.setConfig(config);//提交post访问请求并获得返回值//System.out.println("request: " + httpPost.getRequestLine());try {CloseableHttpClient httpClient = HttpClients.createDefault();CloseableHttpResponse response = httpClient.execute(httpGet); //throwHttpEntity httpEntity = response.getEntity();//System.out.println("response status: " + response.getStatusLine());result = EntityUtils.toString(httpEntity, "UTF-8"); //throw//System.out.println("result: " + result);try {response.close(); //throw}catch(Exception e) {}httpClient.close(); //throw}catch(Exception e) {}//httpGet.abort();return result;}/** * @tutorial 支持http,https * @param string $url 要访问的站点 * @param  mixed $data post可以是任意类型的数据,例如string,array,object,json等 * @param int $timeout 超时时间,单位秒 * @return 站点数据或失败信息 */static public Object post(String url, Object data, int timeout/* = 30*/) {String result = "";//创建http请求(post方式)HttpPost httpPost = new HttpPost(url);httpPost.addHeader("Content-Type", "text/html; charset=UTF-8");//得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别if(data != null && data instanceof String) { //支持上传字符串,如text,xml,jsonStringEntity stringEntity = new StringEntity(data.toString(), "UTF-8");httpPost.setEntity(stringEntity);}else if(data != null && data instanceof byte[]) { //支持上传原始数据,如文件ByteArrayEntity byteArrayEntity = new ByteArrayEntity((byte[])data);httpPost.setEntity(byteArrayEntity);}//设置请求器配置:如超时限制等RequestConfig config = RequestConfig.custom().setSocketTimeout(timeout * 1000).setConnectTimeout(timeout * 1000).build();httpPost.setConfig(config);//提交post访问请求并获得返回值//System.out.println("request: " + httpPost.getRequestLine());try {CloseableHttpClient httpClient = HttpClients.createDefault();CloseableHttpResponse response = httpClient.execute(httpPost); //throwHttpEntity httpEntity = response.getEntity();//System.out.println("response status: " + response.getStatusLine());result = EntityUtils.toString(httpEntity, "UTF-8"); //throw//System.out.println("result: " + result);try {response.close(); //throw}catch(Exception e) {}httpClient.close(); //throw}catch(Exception e) {}//httpPost.abort();return result;}/** * @tutorial 支持http,https * @param string $url 要访问的站点 * @param string $field 文件域.微信公众号一般为"media" * @param string $file 要上传的文件名.可以是相对路径或绝对路径 * @param array $extra 额外要上传的字段.类型为key/value数组.数组元素中key为string类型,value可以是mixed类型. * 例如:在上传视频素材时需要POST另一个表单,id为description,包含素材的描述信息,内容格式为JSON字符串. * array('merchant' => '微微花语商城', 'description' =>'{"title": "猜灯谜抢红包活动", "introduction": "感谢您参加猜灯谜活动,祝您节日快乐"}' * 调用方式为: * ****$ curl -F media=@media.file -F merchant='微微花语商城' -F description='{"title": "猜灯谜抢红包活动", "introduction": "感谢您参加猜灯谜活动,祝您节日快乐"}' "http://localhost/weixin/server.php" * 对应表单为: * <form method="post" enctype="multipart/form-data; charset=UTF-8" action="http://localhost/weixin/server.php"> *     <input type='file' name='media' /> *     <input type='text' name='merchant' value='微微花语商城' /> *     <input type='text' name='description' value='{"title": "猜灯谜抢红包活动", "introduction": "感谢您参加猜灯谜活动,祝您节日快乐"}'> * </form> * @param int $timeout 超时时间,单位秒 * @return 站点数据或失败信息 * @see * ****以下2者的调用方式,效果是一样的: * ****curl_http_upload("http://localhost/weixin/server.php", "media", "a.jpg", null, 30); * ****$ curl -F "media=@a.jpg" "http://localhost/weixin/server.php" * ****后台得到的$_FILES应该为: * ****array("media" => array("name" => "a.jpg", "type" => "image/jpeg", "tmp_name" => "C:\wamp\tmp\php9CC4.tmp", "error" => 0, "size" => 46192)); * @category * ****注:和php版比较,这里稍微美中不足的是,后台得到的mimetype不是真正的类型: * ****array("media" => array("name" => "a.jpg", "type" => "application/octet-stream", "tmp_name" => "C:\wamp\tmp\php9CC4.tmp", "error" => 0, "size" => 46192)); */static public Object upload(String url, String field, String file, Object extra/* = null*/, int timeout/* = 30*/) {String result = "";//创建http请求(post方式)HttpPost httpPost = new HttpPost(url);/***********************************************************************//httpPost.setHeader("Content-Type", "multipart/form-data; charset=UTF-8");//builder.setCharset(Charset.forName(HTTP.UTF_8)); //设置请求的编码格式//builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);//设置浏览器兼容模式上面高亮的两个地方就是在微信素材上传时的两个大坑.1.当遇到乱码时,第一错觉就是设置请求的编码格式,恰恰在微信上传时,如果设置这个编码,就会导致多媒体文件丢失,上传不成功.(具体原因不明)2.设置浏览器兼容模式,这个好多文章说,设置成BOWSER_COMPATIBLE就不会乱码了,问题就出现在这里,设置模式时,应该设置成HttpMultipartMode.RFC6532,这样才是真正的不会出现乱码.3.不要设置编码,模式设置要注意.详见<<HttpClient上传文件到微信素材乱码问题解决>>: http://blog.csdn.net/kookob/article/details/46914777***********************************************************************///httpPost.addHeader("Content-Type", "multipart/form-data; charset=UTF-8"); //"text/html; charset=UTF-8" //"multipart/form-data; charset=UTF-8" //ContentType.MULTIPART_FORM_DATA.toString()//得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别//StringEntity stringEntity = new StringEntity(data.toString(), "UTF-8");//httpPost.setEntity(stringEntity);//添加表单项MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532); //BROWSER_COMPATIBLE自定义charset,RFC6532=utf-8,STRICT=iso-8859-1//$filename = realpath($file); //>>??这两个功能后期要加上//$mimetype = mime_content_type($filename); //如果不手动设置$mimetype,curl会默认为"application/octet-stream"builder.addBinaryBody(field, new File(file));//builder.addPart(field, new FileBody(new File(file)));if(extra != null && !extra.equals("") && extra instanceof Map) {@SuppressWarnings("unchecked")Map<String, Object> map = (Map<String, Object>)extra;for(Map.Entry<String, Object> entry : map.entrySet()) {String key = entry.getKey() != null ? entry.getKey().toString() : "";String val = entry.getValue() != null ? entry.getValue().toString() : "";if(key.equals(""))continue;//param += key + "=" + val + "&";builder.addTextBody(key, val, ContentType.create("text/plain", "UTF-8"));}}if(extra != null && !extra.equals("") && extra instanceof JSONObject) {JSONObject map = (JSONObject)extra;for(String key : map.keySet()) {if(key == null || key.equals(""))continue;String val = map.optString(key);if(val == null)continue;//param += key + "=" + val + "&";builder.addTextBody(key, val, ContentType.create("text/plain", "UTF-8"));}}httpPost.setEntity(builder.build());//设置请求器配置:如超时限制等RequestConfig config = RequestConfig.custom().setSocketTimeout(timeout * 1000).setConnectTimeout(timeout * 1000).build();httpPost.setConfig(config);//提交post访问请求并获得返回值//System.out.println("request: " + httpPost.getRequestLine());try {CloseableHttpClient httpClient = HttpClients.createDefault();CloseableHttpResponse response = httpClient.execute(httpPost); //throwHttpEntity httpEntity = response.getEntity();//System.out.println("response status: " + response.getStatusLine());result = EntityUtils.toString(httpEntity, "UTF-8"); //throw//System.out.println("result: " + result);try {response.close(); //throw}catch(Exception e) {}httpClient.close(); //throw}catch(Exception e) {e.printStackTrace();}//httpPost.abort();return result;}/** * @tutorial 支持http,https * @param string $url 要访问的站点 * @param string $file 保存到本地的文件名,如果需要的话 * @param int $timeout 超时时间,单位秒 * @return 站点数据或失败信息.对于下载来说,成功时的站点数据即为文件的二进制内容. * 对于java版来说,是原始的数据byte[]类型. * 可以直接输出到文件:fs.write(result); * 如果解析成字符串的话,需指定服务器传送过来的编码:new String(result, "ISO-8859-1");new String(result, "UTF-8"); * @see * ****成功返回时: * ****1).如果提供了$file参数,则文件会直接保存到本地; * ****2).同时,将文件的二进制内容作为返回值,可灵活用于缩放,旋转,渲染,保存等. */static public Object download(String url, String file, int timeout/* = 30*/) {byte[] result = null;//创建http请求(post方式)HttpGet httpGet = new HttpGet(url);httpGet.addHeader("Content-Type", "text/html; charset=UTF-8");//得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别//StringEntity stringEntity = new StringEntity(data.toString(), "UTF-8");//httpGet.setEntity(stringEntity);//设置请求器配置:如超时限制等RequestConfig config = RequestConfig.custom().setSocketTimeout(timeout * 1000).setConnectTimeout(timeout * 1000).build();httpGet.setConfig(config);//提交post访问请求并获得返回值//System.out.println("request: " + httpPost.getRequestLine());try {CloseableHttpClient httpClient = HttpClients.createDefault();CloseableHttpResponse response = httpClient.execute(httpGet); //throwHttpEntity httpEntity = response.getEntity();//System.out.println("response status: " + response.getStatusLine());//result = EntityUtils.toString(httpEntity, "UTF-8"); //throwresult = EntityUtils.toByteArray(httpEntity); //throw//System.out.println("result: " + result);try {response.close(); //throw}catch(Exception e) {}httpClient.close(); //throw}catch(Exception e) {}//httpGet.abort();if(result != null && result.length > 0 && file != null && !file.equals("")) {try {OutputStream fs = new FileOutputStream(file);fs.write(result);fs.close();}catch(Exception e) {}}return result;}}

        着重说明的是,微信公众号上传素材时,不需要设置Content-Type头,这一点很重要,我就调试了很久,才在一个大神文章里找到问题关键.详见<<HttpClient上传文件到微信素材乱码问题解决>>: http://blog.csdn.net/kookob/article/details/46914777


0 0
原创粉丝点击