restTemplate.postForObject上传文件中文乱码(???.xls)
一、问题描述
项目中, 使用restTemplate上传文件时, 文件名中文乱码, 一串问号, 源文件名为: 测试中文乱码哦哦哦.zip, 通过restTemplate.postForObject调用接口, 发现文件名变成了: ?????????.zip, 上传失败
二、话不多说, 解决方案
1、新建MyFormHttpMessageConverter类
package com.cn.pinliang.admin.Configure;
import javax.mail.internet.MimeUtility;
import org.springframework.http.converter.FormHttpMessageConverter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class MyFormHttpMessageConverter extends FormHttpMessageConverter {
@Override
protected String getFilename(Object part) {
String filename = super.getFilename(part);
Charset multipartCharset = StandardCharsets.UTF_8;
return MimeDelegate.encode(filename, multipartCharset.name());
}
private static class MimeDelegate {
private MimeDelegate() {
}
public static String encode(String value, String charset) {
try {
return MimeUtility.encodeText(value, charset, (String) null);
} catch (UnsupportedEncodingException var3) {
throw new IllegalStateException(var3);
}
}
}
}
2、新建RestTemplateConf类
package com.cn.pinliang.admin.Configure;
import org.springframework.http.MediaType;
import org.springframework.http.converter.*;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class RestTemplateConf {
public static RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
messageConverters.add(new MappingJackson2HttpMessageConverter());
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
stringHttpMessageConverter.setWriteAcceptCharset(true);
List<MediaType> mediaTypeList = new ArrayList<>();
mediaTypeList.add(MediaType.ALL);
for (int i = 0; i < messageConverters.size(); i++) {
HttpMessageConverter<?> converter = messageConverters.get(i);
if (converter instanceof StringHttpMessageConverter) {
messageConverters.remove(i);
messageConverters.add(i, stringHttpMessageConverter);
}
if (converter instanceof MappingJackson2HttpMessageConverter) {
try {
((MappingJackson2HttpMessageConverter) converter).setSupportedMediaTypes(mediaTypeList);
} catch (Exception e) {
e.printStackTrace();
}
}
if (converter instanceof FormHttpMessageConverter) {
MyFormHttpMessageConverter myConverter = new MyFormHttpMessageConverter();
myConverter.setCharset(StandardCharsets.UTF_8);
messageConverters.remove(i);
messageConverters.add(i, myConverter);
}
}
return restTemplate;
}
}
3、使用
RestTemplate restTemplate = RestTemplateConf.restTemplate();
restTemplate.postForObject... 巴拉巴拉
三、分析
本来之前遇到过同样的问题, 是springboot项目, spring-web版本为4.2.8, 解决方案更简单, 直接在Application启动类中注入restTemplate bean
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
stringHttpMessageConverter.setWriteAcceptCharset(true);
List<MediaType> mediaTypeList = new ArrayList<>();
mediaTypeList.add(MediaType.ALL);
for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) {
HttpMessageConverter<?> converter = restTemplate.getMessageConverters().get(i);
if (converter instanceof StringHttpMessageConverter) {
restTemplate.getMessageConverters().remove(i);
restTemplate.getMessageConverters().add(i, stringHttpMessageConverter);
}
if(converter instanceof MappingJackson2HttpMessageConverter){
try{
((MappingJackson2HttpMessageConverter) converter).setSupportedMediaTypes(mediaTypeList);
}catch(Exception e){
e.printStackTrace();
}
}
if (converter instanceof FormHttpMessageConverter) {
((FormHttpMessageConverter) converter).setCharset(StandardCharsets.UTF_8);
((FormHttpMessageConverter) converter).setMultipartCharset(StandardCharsets.UTF_8);
}
}
return restTemplate;
}
重点是这一行代码
((FormHttpMessageConverter) converter).setMultipartCharset(StandardCharsets.UTF_8);
设置MultipartCharset字符集为UTF-8, 搞定
但是, 现在项目不是springboot项目, 直接copy这段代码发现报错, 没有setMultipartCharset方法, 对比发现原因是spring-web版本不同, 现在是4.0.2, 没有multipartCharset变量
那么问题来了, 怎么解决, 升级版本? 想了想升级版本成本太高, 很有可能导致其他问题, 那既然是由于没有multipartCharset变量, 那就看这个变量到底干了啥能解决中文乱码问题, 跟踪代码发现
原来是获取文件名时用到了, 如果自定义了multipartCharset字符集, 则按照字符集进行转码, 否则直接返回文件名, 再来看下4.0.2版本getFilename方法怎么写的
对, 就这么简单, 没有任何转码, OK, 既然我们无法通过构造参数指定编码从而对文件名进行转码, 那为什么不重写getFilename方法呢, 直接在方法里面指定字符集为UTF-8不就行了?
试一下, 新建MyFormHttpMessageConverter继承FormHttpMessageConverter, 重写getFilename
@Override
protected String getFilename(Object part) {
String filename = super.getFilename(part);
Charset multipartCharset = StandardCharsets.UTF_8;
return MimeDelegate.encode(filename, multipartCharset.name());
}
这一步搞定, 现在定义restTemplate, 最重要的是这一段代码
if (converter instanceof FormHttpMessageConverter) {
MyFormHttpMessageConverter myConverter = new MyFormHttpMessageConverter();
myConverter.setCharset(StandardCharsets.UTF_8);
messageConverters.remove(i);
messageConverters.add(i, myConverter);
}
将原来的FormHttpMessageConverter替换为上面新建的MyFormHttpMessageConverter, 搞定, 测试如下
四、总结
解决bug是一个不断摸索的过程, 尤其是碰到版本类似的问题, 很麻烦, 需要静下心来定位问题, 分析问题, 找出解决方案, 然后不断测试, 最后搞定, 本文没有对RestTemplate的HttpMessageConverter里面的各种转换器进行分析(我也不会, 哈哈), 更多的是一种解决问题的思路, 希望对小伙伴有一点帮助
restTemplate.postForObject上传文件中文乱码(???.xls)的更多相关文章
- drupal7 上传文件中文乱码
drupal7自带有file模块,可以上传文件. 但是存在问题:如果上传的文件名称是中文,存储在文件下面的文件名称是乱码的,解决办法如下:参考出处 includes/file.inc中,修改两处代码, ...
- Spring MVC—拦截器,文件上传,中文乱码处理,Rest风格,异常处理机制
拦截器 文件上传 -中文乱码解决 rest风格 异常处理机制 拦截器 Spring MVC可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现HandlerI ...
- php上传文件中文文件名乱码的解决方法
文件上传是我们在处理表单提交时候最常用的功能之一,今天写了一个小小的demo,如下: 先看结构: html为表单提交的页面,php为处理表单的文件,upload为上传文件所放的位置 html: < ...
- 关于commons-fileupload组件上传文件中文名乱码问题
java web开发,常用到的文件上传功能,常用的commons-fileupload和commons-io两个jar包.关于如何使用这两个jar来完成文件上传的功能,这里不做详解.使用commons ...
- Linux学习23-Xftp上传文件显示乱码问题
前言 当我们在windows新建一个文件,里面有中文时,使用Xftp上传到linux服务器上,会出现乱码问题. Windows的默认编码为GBK Linux的默认编码为UTF-8 Xftp上传文件乱码 ...
- 关于TomCat上传文件中文名乱码的问题
最近在学习TomCat文件上传这一部分,由于文件上传必须要三个条件: 1.表单提交方式必须为Post 2.表单中需要有<input type="file">元素,还需要 ...
- C# 使用 fckeditor 上传文件中文名乱码的问题---转
提到中文乱码,首先肯定是由于编码问题引起的所以就从编码转换入手,尝试了将UTF-8转换为GB2312,但发现无论如何没有办法转成功 看到很多文章说修改配置文件 <globalization re ...
- 中文乱码问题(使用Servlet3.0新特性实现文件上传——上传文件名中文乱码问题)
问题描述:就是文件传送过来的文件名等是乱码 解决方法:将传送的JSP页面(即含有表单的页面)的页面编码方式改为: <%@ page contentType="text/html; ch ...
- 上传文件中文文件名乱码的解决方法以及iconv函数的使用
http://www.jb51.net/article/14530.htm 一般客户端是什么格式就展示什么格式,比如浏览器的UTF-8,windows的GBK
随机推荐
- Educational Codeforces Round 36
A. Garden 题目链接:http://codeforces.com/contest/915/problem/A 题意:N个花洒,每个花洒浇花有一定的范围,现在有面积为K的花园,从N个花洒中选一个 ...
- mac系统 pip3 install scrapy 失败 No local packages or working download links found for incremental>=16.10.1
使用pip3 install scrapy命令之后,会出现如下问题: Collecting scrapy Downloading Scrapy-1.4.0-py2.py3-none-any.whl ( ...
- Pyinstaller打包django
偶有特殊要求可能需要将django程序打包成exe可执行文件,方便在电脑直接点击运行.这里用的是打包python代码的常用库Pyinstaller. 虽然用Pyinstaller支持打包Django, ...
- h5页面关于复制某段文字
上次的项目有一段内容是点击复制按钮 然后复制一段文字,此段方法我才用的是range.selectNodeContents方法,range对象的SelectNodeContents方法将于range对象 ...
- Numpy1
列表转n维数组ndarray import numpy as np list=[1,2,3,4] n=np.array(list) random模块生成ndarray n1=np.random.ran ...
- 将preg_replace()改写为preg_replace_callback()
preg_replace()函数使用/e修饰符可能带来安全隐患,PHP5.5之后,该用法被抛弃使用,升级为preg_replace_callback().在新版本下运行老版本的代码,会出现错误,如: ...
- JSP与Servlet的关系
之前的文章里有说过,其实Servlet比JSP出现的早,JSP的本质就是Servlet,但是一个是jsp页面,一个是java类,硬要说他们的本质是一样的,搁谁都有点难以置信.后面的结论会更加让你吃惊. ...
- Hadoop-2.0 目录简介
Hadoop-2.0 目录简介 一.目录结构 将下载的压缩包解压: 解压后文件夹如下: 二.各文件夹目录结构 1.bin:Hadoop2.0的最基本管理脚本和使用脚本所在目录.这些脚本是sbin目录下 ...
- Eigen3安装及注意
执行命令: sudo apt-get install libeigen3-dev 安装后执行以下命令 运行命令: sudo cp -r /usr/include/eigen3/Eigen /usr/i ...
- C++反汇编(一)
对象/结构体 对象的大小只包括数据成员,成员函数属于执行代码. 对象长度 = sizeof(数据成员1) + sizeof(数据成员2) + ...... + sizeof(数据成员n) 特殊情况公式 ...