HttpClient多文件上传代码及普通参数中文乱码问题解决
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接⼝。下⾯提供了使⽤时的代码实现,包括服务端和客户端。
不过,笔者在使⽤的过程中发现,当传递的普通参数有中⽂时,对⽅接到的参数会乱码,因为开始笔者使⽤的是multipartEntity.addTextBody(key, (key));的⽅式设置普通参数。
为了解决乱码问题,最后查到了解决办法,记录如下。
如下代码是可以上传多个⽂件和普通参数的,使⽤ multipart/form-data + POST ⽅式提交,模拟浏览器在页⾯上 form表单的提交⽅式。
1/**
2    * httpclient ⽂件上传
3    * @param postFiles
4    * @param postUrl
5    * @param postParam
6    * @return
7*/
8public static Map<String, Object> uploadFileByHttpPost(File[] postFiles, String postUrl, Map<String, String> postParam) {
9        Map<String, Object> resultMap = new HashMap<String, Object>();
10        CloseableHttpClient httpClient = ateDefault();
11try {
12//把⼀个普通参数和⽂件上传给下⾯这个api接⼝
13            HttpPost httpPost = new HttpPost(postUrl);
14//设置传输参数,设置编码。设置浏览器兼容模式,解决⽂件名乱码问题
15            MultipartEntityBuilder multipartEntity = ate().setMode(HttpMultipartMode.RFC6532);
16for (int i = 0; i < postFiles.length; i++) {
17                File postFile = postFiles[i];
18                FileBody fundFileBin = new FileBody(postFile, ContentType.MULTIPART_FORM_DATA);
19
20//相当于<input type="file" name="media"/>
21                multipartEntity.addPart("upload_file"+i, fundFileBin);
22            }
23//把⽂件转换成流对象FileBody
24            Set<String> keySet = postParam.keySet();
25for (String key : keySet) {
26//解决中⽂乱码
27                ContentType contentType = ate("text/plain", Charset.forName("UTF-8"));
28                StringBody stringBody = new (key), contentType);
29                multipartEntity.addPart(key, stringBody);
30// multipartEntity.addTextBody(key, (key));//这个中⽂会乱码
31            }
32            HttpEntity reqEntity = multipartEntity.build();
33            httpPost.setEntity(reqEntity);
34//发起请求并返回请求的响应
35            CloseableHttpResponse response = ute(httpPost);
36try {
37//打印响应状态
38                resultMap.put("statusCode", StatusLine().getStatusCode());
39//获取响应对象
40                HttpEntity resEntity = Entity();
41if (resEntity != null) {
软件乱码怎么办
42//打印响应内容
43                    resultMap.put("data", String(resEntity, Charset.forName("UTF-8")));
44                }
45//销毁
46                sume(resEntity);
47            } catch (Exception e) {
48                e.printStackTrace();
49            } finally {
50                response.close();
51            }
52        } catch (ClientProtocolException e1) {
53            e1.printStackTrace();
54        } catch (IOException e1) {
55            e1.printStackTrace();
56        } finally {
57try {
58                httpClient.close();
59            } catch (IOException e) {
60                e.printStackTrace();
61            }
62        }
63return resultMap;
64    }
这是客户端上传的代码,我们看⼀下怎么接收,使⽤SpringMVC controller层接收⽂件和普通参数:
1/**
2    * 上传⽂件
3    * @throws IOException
4    * @throws IllegalStateException
5*/
6    @RequestMapping("/postFile")
7    @ResponseBody
8public String postFile(HttpServletRequest request){
9        Map<String, Object> map = new HashMap<String, Object>();
10// 创建⼀个通⽤的多部分解析器
11        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request
12                .getSession().getServletContext());
13        String name = Parameter("name");
14        String age = Parameter("age");
15
16        System.out.println(name+","+age);
17        Session().getServletContext();
18// 判断 request 是否有⽂件上传,即多部分请求
19if (multipartResolver.isMultipart(request)) {
20// 转换成多部分request
21            MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
22// 取得request中的所有⽂件名
23            Iterator<String> iter = FileNames();
24while (iter.hasNext()) {//多⽂件
25// 取得上传⽂件
26                MultipartFile multipartFile = ());
27if (null != multipartFile) {
28// 取得当前上传⽂件的⽂件名称
29                    String fileName = OriginalFilename();
30if (im() != null && im().length() > 0) {
31                        CommonsMultipartFile cf = (CommonsMultipartFile) multipartFile;
32                        DiskFileItem fi = (DiskFileItem) cf.getFileItem();
33                        File tempFile = fi.getStoreLocation();
34// 拿到⽂件,存储
35try {
36                            ansferTo(new File("F:\\static\\page\\"+OriginalFilename()));
37                        } catch (IOException e) {
38                            e.printStackTrace();
39return "error";
40                        }
41                    }
42                }
43            }
44        }
45return "success";
46    }
1public static void main(String[] args) {
2        String url = "localhost:8080/postFile";
3        File[] files = new File[2];
4        files[0] = new File("F:\\static\\updateFile-demo.docx");
5        files[1] = new File("F:\\static\\updateFile-demo02.docx");
6
7        Map<String,String> param = new HashMap<>();
8        param.put("name","编程⼤道");
9        param.put("age","18");
10
11        Map<String, Object> stringObjectMap = HttpClientUtil01.uploadFileByHttpPost(files, url, param);
12        System.out.println(stringObjectMap);
13    }
我们上传两个⽂件和两个普通参数,服务端controller⾥的处理是,打印这两个普通参数并把两个⽂件保存到page⽬录下
启动服务
我们先启动服务端,如下图正常启动
运⾏测试类,控制台输出如下:
服务端输出:
查看是否保存成功
成功!!
但是在成功之前也遇到了问题,如下:上传⽂件:
传普通参数,注意中⽂乱码的问题:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。