项目总结-利用HttpClient发送表单数据

        项目开发过程中,由于使用百度平台云资源有限,在做微信多媒体资源上传时没有存储空间,百度云平台上只有临时文件目录的写权限,资源临时存储后调用微信公众平台API完成资源上传。本项目的资源由于没有足够空间,只能折中存储在公司外网文件服务器上,通过发送http请求给文件服务器,由其去下载图片存储到本地,返回存储目录给项目服务器。请求参数有两个imgUrl和msgId,分别指定图片下载路径和存储名称。

        下载图片代码如下:       

        /**
	 * 下载图片到本地
	 */
	private String  downloadImage(MsgRequest msgRequest) {
		//远程下载请求参数
		String picUrl = msgRequest.getPicUrl();
		String msgId = msgRequest.getMsgId();
		String para = String.format("/api/putimg?imgUrl=%s&msgId=%s",picUrl,msgId);
		StringBuffer buffer = new StringBuffer();
		buffer.append(Constants.FileServerUrl);
		buffer.append(para);
		
		String result = null;
		String response = WeChatApiUtil.httpRequestToString(buffer.toString(), "POST", null);
		JSONObject object = JSONObject.fromObject(response);
		if(object!=null&&object.getBoolean("status")){
			logger.info("下载故障图片到文件服务器:"+object.toString());
			//拼接存储全路径
			result = Constants.FileServerUrl+object.getString("data");
		}else{
			logger.info("response null.");
		}
		
		return result;
	}

          如果imgUrl的参数值仅仅是一个路径,不包含参数信息,下载没有问题。但是如果imgUrl的值是一个带有参数信息的下载地址,那么拼接完成后,文件服务器端处理参数时将会忽略无用的&之后的参数(&作为参数分隔符),只获取它需要的两个参数imgUrl和msgId

         例如我的文件下载地址包含一个参数,直接拼接远程下载请求为:

        http://172.17.X.XX:80801/api/putimg?imgUrl=http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s&msgId=mediaId

         此时文件下载服务器解析到的下载地址imUrl为http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=,并不包含下一个参数。这就直接导致文件下载失败,分析之后发现服务器端收到的imgUrl参数缺少media_id。发送这样的参数信息可以通过发送表单数据来保证参数的正确。模拟post发送表单数据的代码如下:

        /**
	 * 表单数据通过post发送
	 * @param url
	 * @param httpClient
	 * @param picUrl
	 * @return
	 */
	public static String postFormData(String url,Map<String,String>data) {
		//需要发送时再创建
		synchronized (FileUtil.class) {
			if(httpClient==null){
				httpClient = new HttpClient();
			}
		}
		
		String response = null;
		PostMethod method = new PostMethod(url);

		method.addRequestHeader("User-Agent","Mozilla/5.0 (Windows NT 5.1; rv:25.0) Gecko/20100101 Firefox/25.0");
		// 设置请求体也就是请求的表单提交数据:form表单提交的数据
		NameValuePair[] paires = null;
		if(data!=null&&data.size()>0){
			paires = new NameValuePair[data.size()];
			int index = 0;
			for(Entry<String, String> entry:data.entrySet()){
				NameValuePair pair = new NameValuePair(entry.getKey(),entry.getValue());
				paires[index] = pair;
				index++;
			}
			//请求参数作为数据请求体
			method.setRequestBody(paires);
		}
		
		try {
			httpClient.executeMethod(method);
			int statusCode = method.getStatusCode();
			System.out.println("statusCode:" + statusCode);

			// 获取响应返回的信息
			InputStream in = method.getResponseBodyAsStream();
			BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
			StringBuffer buffer = new StringBuffer();
			String info = reader.readLine();
			while (info != null) {
				buffer.append(info);
				buffer.append("\n");
				info = reader.readLine();
			}
			response = buffer.toString();
			method.releaseConnection();
		} catch (HttpException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return response;
	}

          由于文件下载请求并不总是发送,所以HttpClient对象在用到的时候再new,默认为空,创建操作放在同步块中。需要注意的时synchronized的锁可以是类类型(XX.class)也可以是某个对象(必须是非null对象,否则会抛空指针异常)。

         结论:

          post发送的表单数据会被解析成请求的参数信息,使用SpringMVC开发时,通常我们使用Action提交表单时,表单数据被添加到http请求的body中,而且设置了其它额外的属性(例如content-type),保证服务器将其解析成请求参数。通过wirshark抓包信息就可以看出,body中是普通数据和表单数据,包的内容是不一样的。值得深究。

              
 

        



表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页
实付 9.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值