使用HttpClient MultipartEntityBuilder 上传文件,并解决中文文件名乱码问题
遇到一种业务场景,前端上传的文件需要经过java服务转发至文件服务。期间遇到了原生HttpClient怎么使用的问题、怎么把MultipartFile怎么重新组装成Http请求发送出去的问题、文件中文名乱码问题。最后都解决了,先上代码,再讲遇到的坑
- @Slf4j
- @Service
- public class FileServiceImpl implements IFileService {
- @Value("${FileService.putUrl}")
- private String putUrl;
- @Value("${FileService.app_id}")
- private String appId;
- @Value("${FileService.securityKey}")
- private String secureKey;
- private final static String UPLOAD_RESPONSE_CODE = "error";
- private final static Integer UPLOAD_RESPONSE_SUCCESS = 0;
- @Override
- public String upload(MultipartFile file) {
- int timeOut = 30000;
- CloseableHttpClient httpClient = HttpClientBuilder.create().build();
- HttpHost proxy = new HttpHost("127.0.0.1", 62145, "http"); //设置本地fiddler代理,方便排查问题
- RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeOut)
- .setConnectTimeout(timeOut).setSocketTimeout(timeOut).setProxy(proxy).build();
- HttpPost httpPost = new HttpPost(putUrl);
- httpPost.setConfig(requestConfig);
- try {
- //BROWSER_COMPATIBLE自定义charset,RFC6532=utf-8,STRICT=iso-8859-1
- //此处一定要用RFC6532,网上普遍用的BROWSER_COMPATIBLE依然会出现中文名乱码
- MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
- //multipartEntityBuilder.setCharset(Charset.forName("UTF-8")); //此处踩坑,转发出去的filename依然为乱码
- //ContentType contentType = ContentType.create("multipart/form-data",Charset.forName("UTF-8")); //此处也是坑,转发出去的filename依然为乱码
- multipartEntityBuilder.addBinaryBody("file", file.getInputStream(), ContentType.DEFAULT_BINARY, file.getOriginalFilename());
- multipartEntityBuilder.addTextBody("app_id", appId); //可替换成你自己需要的附加字段
- long time = System.currentTimeMillis() / 1000;
- multipartEntityBuilder.addTextBody("time", String.valueOf(time)); //可替换成你自己需要的附加字段
- String beforeSign = String.format("app_id=%s&time=%s%s", appId, time, secureKey);
- String sign = MD5Util.md5(beforeSign);
- multipartEntityBuilder.addTextBody("sign", sign); //可替换成你自己需要的附加字段
- HttpEntity requestEntity = multipartEntityBuilder.build();
- httpPost.setEntity(requestEntity);
- HttpResponse httpResponse = httpClient.execute(httpPost);
- int statusCode= httpResponse.getStatusLine().getStatusCode();
- if (statusCode != 200) throw new BizException(BizCode.INNER_SERVICE_ERROR, "响应状态码为:" + statusCode);
- HttpEntity responseEntity = httpResponse.getEntity();
- return getUrlString(EntityUtils.toString(responseEntity));
- } catch (Exception e) {
- log.error("发送文件异常:{}", e);
- throw new BizException(BizCode.INNER_SERVICE_ERROR, "发送文件服务异常:" + e.getMessage());
- } finally {
- try {
- httpClient.close();
- } catch (IOException e) {
- log.error("关闭httpClient异常:" + e.getMessage(), e);
- }
- }
- }
- private String getUrlString(String jsonString) {
- try{
- log.debug("解析json串:"+ jsonString);
- JSONObject jsonObject = JSONObject.parseObject(jsonString);
- if (jsonObject.getInteger(UPLOAD_RESPONSE_CODE) != UPLOAD_RESPONSE_SUCCESS) {
- log.error("文件服务返回错误:" + jsonObject.getString("data"));
- throw new OtherServiceReturnErrorException("文件服务返回错误:" + jsonObject.getString("data"));
- }
- return ((JSONObject)jsonObject.get("data")).get("original").toString();
- }catch (Exception e) {
- log.error("文件服务返回json解析错误:" + jsonString);
- throw new OtherServiceReturnErrorException("文件服务返回json解析错误:" + jsonString);
- }
- }
- }
特别说明及遇到的坑:
1. 这里基于tomcat进行请求转发,需要在代码中手动添加代理:
- HttpHost proxy = new HttpHost("127.0.0.1", 62145, "http"); //设置本地fiddler代理,方便排查问题
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeOut)
.setConnectTimeout(timeOut).setSocketTimeout(timeOut).setProxy(proxy).build();
2. MultipartFile通过getInputStream()可以将流设置到MultipartEntityBuilder中,其中addBinaryBody里面的ContentType 和 filename必须设置,要不然后续服务读取不到这个文件流
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
multipartEntityBuilder.addBinaryBody("file", file.getInputStream(), ContentType.DEFAULT_BINARY, file.getOriginalFilename());
3. file.getOriginalFilename()方法虽然没有乱码,但是addBinaryBody后,组装的Http请求出去总是乱码,如下图:
踩了各种坑,如为MultipartEntityBuilder设置Charset或者是手动设置ContentType,都无法解决此问题,文件名依然是上图所示乱码
后来发现在MultipartEntityBuilder中设置Mode为HttpMultipartMode.RFC6532可以完美解决这个问题,并且不再需要单独设置ContentType或Charset,因为HttpMultipartMode.RFC6532就告诉了MultipartEntityBuilder,里面的数据都要使用UTF-8进行处理,fiddler抓到的请求发现filename成功变成中文名。
done
使用HttpClient MultipartEntityBuilder 上传文件,并解决中文文件名乱码问题的更多相关文章
- CuteFTP 9.0 上传文件时,中文文件名乱码
解决办法如图: 1.右键--->属性 2.选项---->档案名称编 选择ascⅡ
- HttpClient MultipartEntityBuilder 上传文件
文章转载自: http://blog.csdn.net/yan8024/article/details/46531901 http://www.51testing.com/html/56/n-3707 ...
- dotnetcore下解压zip文件,解决中文文件名乱码问题
(迄今为止网上那些说的用Encoding.Default解决中文文件名乱码的都不能真正解决问题!) 1.在程序开始处 Encoding.RegisterProvider(CodePagesEncodi ...
- python向ftp上传文件,解决中文问题
# coding: UTF-8 import os import sys import salt.client import salt.config import time from ftplib i ...
- 转 Android网络编程之使用HttpClient批量上传文件 MultipartEntityBuilder
请尊重他人的劳动成果,转载请注明出处:Android网络编程之使用HttpClient批量上传文件 http://www.tuicool.com/articles/Y7reYb 我曾在<Andr ...
- Android 发送HTTP GET POST 请求以及通过 MultipartEntityBuilder 上传文件(二)
Android 发送HTTP GET POST 请求以及通过 MultipartEntityBuilder 上传文件第二版 上次粗略的写了相同功能的代码,这次整理修复了之前的一些BUG,结构也大量修改 ...
- Chrome不能在网易网盘中上传文件的解决办法
Chrome不能在网易网盘中上传文件的解决办法1. 安装 Adobe Flash Player PPAPI,设置flash插件 chrome://settings/content/flash,许可[* ...
- C# 应用 - 使用 HttpClient 发起上传文件、下载文件请求
1. 示例代码 using System; using System.IO; using System.Net.Http; /// <summary> /// 下载文件 /// </ ...
- 利用struts2上传文件时,如果文件名中含有-符号,那么会出错
利用struts2上传文件时,如果文件名中含有-符号,那么会出错 报错如下: HTTP Status 500 - C:\Program Files\Apache Software Foundation ...
随机推荐
- 78-DeMarker,价格波动指数.(2015.7.1)
DeMarker 价格波动指数 观井映天 2015.7.1
- Huawei-R&S-网络工程师实验笔记20190615-IP基础(AR201上配置IP)
>Huawei-R&S-网络工程师实验笔记20190615-IP基础(AR201上配置IP) >>实验开始,先上拓扑图参考: >>>一般正常配置IP操作如下 ...
- Thawte 企业版代码签名证书
Thawte企业版代码签名证书 ,严格验证企业身份,如果您是个人开放者,请申请Thawte 个人代码签名证书.Thawte企业代码签名证书 可帮助程序开发者使用微软代码签名工具(Microsoft ...
- 添物零基础到架构师(基础篇) - JavaScript
JavaScript是什么? JavaScript是web开发必须学习的,ECMAScript是其规则来源. JavaScript的历史 Developed by Brendan Eich of Ne ...
- ZOJ 1298_Domino Effect
题意: 多米诺骨牌效应:若干个关键牌相连,关键牌之间含有普通牌,关键牌倒下后其所在的行的普通牌全部倒下.求从推倒1号关键牌开始,最终倒下的牌的位置及时间. 分析: 最终倒下的牌的位置有两种情况,要么是 ...
- HDU——2063 过山车
过山车 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- mysql性能调优——Query优化
上节谈了关于mysql锁定机制的优化方案,下面来谈一下Query优化——Mysql Query Optimizer 当Mysql Query Optimizer接受到从Query Parser过来的Q ...
- Errors running builder 'JavaScript Validator' on
eclipse编译提示Errors running builder 'JavaScript Validator' on 解决方法见下图 去掉 'JavaScript Validator' 即可
- sql 按中文排序
sql server:select * from [表名]order by [字段],[字段] collate Chinese_PRC_CS_AS_KS_WS mysql:select * from ...
- mybatis返回list很智能很简答的,只需要配置resultmap进行类型转换,你dao方法直接写返回值list<对应的object>就行了啊
mybatis返回list很智能很简答的,只需要配置resultmap进行类型转换,你dao方法直接写返回值list<对应的object>就行了啊 dao方法 public List< ...