2023年12月3日发(作者:)

HttpClient多文件上传代码及普通参数中文乱码问题解决该随笔记录了在实际项目中使用HttpClient调用外部api,需上传文件和普通参数的代码。笔者在使用 HttpClient 调用 http api 接口时,需要服务端上传文件和一些普通参数给 http api,如果使用 Java 自带的 HttpURLConnection 请求的话,发送multipart/form-data + POST 请求会比较麻烦,需要设置一些边界(将文件与文件、文件与普通参数之间隔开,便于接收者截取,这是 http 协议要求的)。因为上传文件和普通参数时,服务端读取报文是根据边界值来截取的,如果使用原生的 HttpURLConnection 则比较麻烦,所以笔者采用 HttpClient 工具,httpclient是apache 软件基金会下的子项目,它很好的封装了Http工具,面向对象的思想省去了很多细节,使程序员关注与业务逻辑处理,不用关注这些通讯细节。笔者使用HTTPClient实现文件的上传,使用 MultipartEntityBuilder 构造请求体,实现 multipart/form-data + POST 请求http接口。下面提供了使用时的代码实现,包括服务端和客户端。不过,笔者在使用的过程中发现,当传递的普通参数有中文时,对方接到的参数会乱码,因为开始笔者使用的是tBody(key,(key));的方式设置普通参数。为了解决乱码问题,最后查到了解决办法,记录如下。如下代码是可以上传多个文件和普通参数的,使用 multipart/form-data + POST 方式提交,模拟浏览器在页面上 form表单 的提交方式。

客户端上传文件及普通参数代码: 1 /** 2 * httpclient 文件上传 3 * @param postFiles 4 * @param postUrl 5 * @param postParam 6 * @return 7 */ 8 public static Map uploadFileByHttpPost(File[] postFiles, String postUrl, Map postParam) { 9 Map resultMap = new HashMap();10 CloseableHttpClient httpClient = Default();11 try {12 //把一个普通参数和文件上传给下面这个api接口13 HttpPost httpPost = new HttpPost(postUrl);14 //设置传输参数,设置编码。设置浏览器兼容模式,解决文件名乱码问题15 MultipartEntityBuilder multipartEntity = ().setMode(6532);16 for (int i = 0; i < ; i++) {17 File postFile = postFiles[i];18 FileBody fundFileBin = new FileBody(postFile, ART_FORM_DATA);19

20 //相当于21 t("upload_file"+i, fundFileBin);22 }23 //把文件转换成流对象FileBody24 Set keySet = ();25 for (String key : keySet) {26 //解决中文乱码27 ContentType contentType = ("text/plain", e("UTF-8"));28 StringBody stringBody = new StringBody((key), contentType);29 t(key, stringBody);30 // tBody(key, (key));//这个中文会乱码31 }32 HttpEntity reqEntity = ();33 ity(reqEntity);34 //发起请求 并返回请求的响应35 CloseableHttpResponse response = e(httpPost);36 try {37 //打印响应状态38 ("statusCode", tusLine().getStatusCode());39 //获取响应对象40 HttpEntity resEntity = ity();41 if (resEntity != null) {42 //打印响应内容43 ("data", ng(resEntity, e("UTF-8")));44 }45 //销毁46 e(resEntity);47 } catch (Exception e) {48 tackTrace();49 } finally {50 ();51 }52 } catch (ClientProtocolException e1) {53 tackTrace();54 } catch (IOException e1) {55 tackTrace();56 } finally {57 try {58 ();59 } catch (IOException e) {60 tackTrace();61 }62 }63 return resultMap;64 }

服务端处理请求代码这是客户端上传的代码,我们看一下怎么接收,使用SpringMVC controller层接收文件和普通参数:

1 /** 2 * 上传文件 3 * @throws IOException 4 * @throws IllegalStateException 5 */ 6 @RequestMapping("/postFile") 7 @ResponseBody 8 public String postFile(HttpServletRequest request){ 9 Map map = new HashMap();10 // 创建一个通用的多部分解析器11 CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request12 .getSession().getServletContext());13 String name = ameter("name");14 String age = ameter("age");15

16 n(name+","+age);17 sion().getServletContext();18 // 判断 request 是否有文件上传,即多部分请求19 if (ipart(request)) {20 // 转换成多部分request21 MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;22 // 取得request中的所有文件名23 Iterator iter = eNames();24 while (t()) {//多文件25 // 取得上传文件26 MultipartFile multipartFile = e(());27 if (null != multipartFile) {28 // 取得当前上传文件的文件名称29 String fileName = ginalFilename();30 if (() != null && ().length() > 0) {31 CommonsMultipartFile cf = (CommonsMultipartFile) multipartFile;32 DiskFileItem fi = (DiskFileItem) eItem();33 File tempFile = reLocation();34 // 拿到文件,存储35 try {36 erTo(new File("F:staticpage"+ginalFilename()));37 } catch (IOException e) {38 tackTrace();39 return "error";40 }41 }42 }43 }44 }45 return "success";46 }

测试代码: 1 public static void main(String[] args) { 2 String url = "localhost:8080/postFile"; 3 File[] files = new File[2]; 4 files[0] = new File("F:"); 5 files[1] = new File("F:"); 6

7 Map param = new HashMap<>(); 8 ("name","编程大道"); 9 ("age","18");10

11 Map stringObjectMap = FileByHttpPost(files, url, param);12 n(stringObjectMap);13 }

代码验证我们上传两个文件和两个普通参数,服务端controller里的处理是,打印这两个普通参数并把两个文件保存到page目录下

启动服务 我们先启动服务端,如下图正常启动 运行测试类,控制台输出如下:服务端输出:查看是否保存成功成功!!

注意事项:但是在成功之前也遇到了问题,如下:上传文件:

传普通参数,注意中文乱码的问题: