HttpClient模拟表单提交数据(File文件类型和普通表单)

HttpClient模拟表单提交数据(File(文件)类型和普通类型)

最近在工作中,因为对方要求使用表单进行上传,但是其中有一个字段是file类型,导致我弄了很久,都无法正确发出,在这里进行记录,希望能给大家一种解决思路。

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;

import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.Test;

public class test {
	@Test
	public void uploadFormFile() {
		CloseableHttpClient httpClient = HttpClientBuilder.create().build();
		int timeOut = 30000;
		// 设置本地fiddler代理,方便排查问题
		//因为是基于tomcat进行的请求转发,所以在代码中手动添加代理
		HttpHost proxy = new HttpHost("127.0.0.1", 8080, "http");
		RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeOut)
				.setConnectTimeout(timeOut).setSocketTimeout(timeOut).setProxy(proxy).build();
		//设置请求地址
		HttpPost httpPost = new HttpPost("XXXX");
		httpPost.setConfig(requestConfig);
		
		/*
		 * 这里是一个很容易被疏忽的地方
		 * 关于表单提交,会有两种content-Type:
		 * 		1、application/x-www-form-urlencoded:不能进行文件的上传,我们一般form表单默认就是这个类型
		 * 		2、multipart/form-data ,用于文件的上传,设置表单的MIME编码,二进制传输数据,参数会以boundary进行分割
		 * 很多人选择文件上传的话,就会直接设置这个地方为multipart/form-data,
		 * 但是这里面有个boundary参数属性,假如我们手动设置为multipart/form-data,则会导致boundary无法生成。所以这里千万不要设置
		 */
		//httpPost.setHeader("content-Type", "multipart/form-data");
		
		//构建参数
		MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
		/*
		 * RFC6532=utf-8,STRICT=iso-8859-1
		 * 这里如果存在中文乱码,一定要用RFC6532
		 * 如果没有中文,这行可以不要
		 */
		multipartEntityBuilder.setMode(HttpMultipartMode.RFC6532);
		
		/*
		 * 这个设置并无卵用,害我纠结了半天是不是编码方式设置错了
		 */
		//multipartEntityBuilder.setCharset(Charset.forName("UTF-8"));
		
		/*
		 * 这个地方是个深渊巨坑!!!!
		 * 这里千万不要设置ContentType = multipart/form-data, 不然 boundary 这个参数就不会自动生成
		 */
		//org.apache.http.entity.ContentType.create("multipart/form-data",Charset.forName("UTF-8"));
		
		/*
		 * 这里也是个深渊巨坑!!!!
		 * 这里是设置需要传输的文件
		 * 第一个参数是key值,也就是对面拿什么来接收
		 * 第二个参数是文件 file
		 * 第三个参数  一种类型,具体也也不太清楚
		 * 第四个参数  这个就是巨坑了!!看源码,当不填这个值的时候,会取file.getName;
		 * 但是一定要记住,如果文件是远程地址的,这样再通过http传的时候会出现错误,所以需要取到最原始的文件后缀名!!!最好就是用字节流去读取这个文件
		 * 
		 * 这里的第三个参数和第四个参数必须要设置,不然后续服务读取不到这个文件流
		 */
		File file = new File("http://aaa/bbb/cc/ddd.jpg");
		multipartEntityBuilder.addBinaryBody("image", file, ContentType.DEFAULT_BINARY, file.getName());
		
		//这里是设置string类型的传输数据
		
		/*
		 * 这里是设置字符编码
		 * 这个地方也是坑,但是网上很多文章都会设置,所以很少人出问题
		 * 根据我的理解,就是整体传输,需要给表单设置一个编码,然后文件传输,也需要设置编码,文字传输,也需要设置编码
		 * 很多小伙伴都会因为某个地方没有设置编码,导致传输失败。这个地方可能理解有误,欢迎大家来指导。
		 */
		org.apache.http.entity.ContentType contentType = 
				org.apache.http.entity.ContentType.create("text/plain",Charset.forName("UTF-8"));
		multipartEntityBuilder.addPart("name", new StringBody("zhangsan", contentType));
		multipartEntityBuilder.addPart("age", new StringBody("18", contentType));
		
		httpPost.setEntity(multipartEntityBuilder.build());
		
		try {
			org.apache.http.HttpResponse response = httpClient.execute(httpPost);
			/*
			 * int statusCode= response.getStatusLine().getStatusCode();
			 * 这里是返回状态码,真正在项目中,需要判断返回码是否为200,看是否发送成功
			 * 这里就不展开写了
			 */
			System.out.println( EntityUtils.toString(response.getEntity(), "UTF-8"));
		} catch (Exception e) {
		}finally {
			try {
				httpClient.close();
			} catch (IOException e) {
			}
		}
		
	}
}

这里还再提供一种普通写法,比较简单,不涉及到文件上传。使用NameValuePair,content-Type为application/x-www-form-urlencoded。

@Test
	public void testForm() {
		CloseableHttpClient httpClient = HttpClientBuilder.create().build();
		int timeOut = 30000;
		// 设置本地fiddler代理,方便排查问题
		//因为是基于tomcat进行的请求转发,所以在代码中手动添加代理
		HttpHost proxy = new HttpHost("127.0.0.1", 8080, "http");
		RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeOut)
				.setConnectTimeout(timeOut).setSocketTimeout(timeOut).setProxy(proxy).build();
		//设置请求地址
		HttpPost httpPost = new HttpPost("XXXX");
		httpPost.setConfig(requestConfig);
		httpPost.setHeader("content-Type", "application/x-www-form-urlencoded");
		
		List<NameValuePair> formParams = new ArrayList<>();
		formParams.add(new BasicNameValuePair("isAllIndustry", "0"));
		try {
			UrlEncodedFormEntity he=new UrlEncodedFormEntity(formParams,"UTF-8");
			httpPost.setEntity(he); 
			HttpResponse response=httpClient.execute(httpPost); 
			System.out.println( EntityUtils.toString(response.getEntity(), "UTF-8"));
		} catch (Exception e) {
			// TODO: handle exception
		}

参考:
https://www.cnblogs.com/evasean/archive/2018/07/25/9368670.html
http://www.cnblogs.com/iscys/p/9595358.html
https://yq.aliyun.com/ziliao/286006

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值