解决resteasy上传表单文件名乱码
Dubbo在2.6版本后合并了dubbox的resteasy代码后,可以支持rest风格的接口发布,但是在使用form表单上传文件的时候,获取的文件名称是乱码。
下面通过对源码分析一下原因,并提供一种可行的解决方法。
首先是一个resteasy上传的使用代码
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Override
public Object uploadfile(MultipartFormDataInput input, @Context HttpServletRequest request, @Context HttpServletResponse response) {
System.out.println("进入业务逻辑");
// MultipartFormDataReader
Map<String, Object> map = null; Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
//取得文件表单名
List<InputPart> inputParts = uploadForm.get("file"); final String DIRCTORY = "D:/temp/datainput/";
initDirectory(DIRCTORY);
InputStream inputStream = null;
OutputStream outStream = null;
for (InputPart inputPart : inputParts) {
try {
// 文件名称
String fileName = getFileName(inputPart.getHeaders());
inputStream = inputPart.getBody(InputStream.class, null);
//把文件流保存;
File file = new File(DIRCTORY + fileName);
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
outStream = new FileOutputStream(file);
outStream.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}finally {
if(null != inputStream){
try {
inputStream.close();
} catch (IOException e) {
}
}
if(null != outStream){
try {
outStream.close();
} catch (IOException e) {
}
}
} } return Response.ok().build();
}
resteasy文件上传使用的Consumes使用的mediattype类型是MULTIPART_FORM_DATE【@Consumes(MediaType.MULTIPART_FORM_DATA)】
这个mediatype使用的Provider使用的是org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataReader,其readForm的入口为
public MultipartFormDataInput readFrom(Class<MultipartFormDataInput> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException
{ String boundary = mediaType.getParameters().get("boundary");
if (boundary == null) throw new IOException(Messages.MESSAGES.unableToGetBoundary());
MultipartFormDataInputImpl input = new MultipartFormDataInputImpl(mediaType, workers);
input.parse(entityStream);
return input;
}
在跟入上面代码的parse方法 input.parse(entityStream)中的new BinaryMessage()构造函数中,MultipartInputImpl对http的head进行了解析
private static class BinaryMessage extends Message
{
private BinaryMessage(InputStream is) throws IOException, MimeIOException
{
try {
MimeStreamParser parser = new MimeStreamParser(null); StorageProvider storageProvider;
if (System.getProperty(DefaultStorageProvider.DEFAULT_STORAGE_PROVIDER_PROPERTY) != null) {
storageProvider = DefaultStorageProvider.getInstance();
} else {
StorageProvider backend = new CustomTempFileStorageProvider();
storageProvider = new ThresholdStorageProvider(backend, 1024);
}
parser.setContentHandler(new BinaryOnlyMessageBuilder(this, storageProvider));
parser.parse(is); // 此处未解析代码,未传入指定的字符串编码方式
} catch (MimeException e) {
throw new MimeIOException(e);
} }
}
在行 parser.parse(is);中,采用的是apache-mime4j-1.6版本的流解析器,由于MultipartInputImpl在调用apache-mime4j的解析方法,没有可指定字符编码的方法,此处编码的设置传递会丢失。(PS:MultipartInputImpl中的defaultPartCharset,可以通过拦截器request.setAttribute(InputPart.DEFAULT_CHARSET_PROPERTY, ENCODING_UTF_8);进行指定)。
后续未指定字符编码的调用链中,apache-mime4j对上传内容的解析采用了默认的ASCII编码进行处理,对应RawField.parseBody()
private String parseBody() {
int offset = colonIdx + 1;
int length = raw.length() - offset;
return ContentUtil.decode(raw, offset, length);
}
该decode方法中使用的是写死的ASCII编码进行处理
public static String decode(ByteSequence byteSequence, int offset,
int length) {
return decode(CharsetUtil.US_ASCII, byteSequence, offset, length);
}
所以看到这里,就了解了为什么文件名称会是乱码的了,大概也知道其他地方通过拦截器设置编码格式解决不了文件名称乱码的问题了。
所以可行的解决方法可以是(亲测可用),将apache-mime4j-1.6的源码导入工程中,并且修改ContentUtil的decode方法,如下:

public static String decode(ByteSequence byteSequence, int offset,
int length) {
return decode(CharsetUtil.UTF_8 //修改此处默认编码
, byteSequence, offset, length);
}
这种方法不好的点就是冗余了一份开源代码到自己项目中,并且项目包路径会比较奇怪。当然也可以编译一份修改后的代码放到自己公司的nexus库中。
解决resteasy上传表单文件名乱码的更多相关文章
- 【Flask】 结合wtforms的文件上传表单
表单中的文件上传 基本的表单渲染,表单类设置等等就不多说了,参看另一个文章即可.但是那篇文章里没有提到对于FileField,也就是上传文件的表单字段是如何处理,后端又是如何实现接受上传过来的文件的. ...
- ajax上传表单的俩种方式
1.用h5对象上传表单(图片) var formData = new FormData(); formData.append("authenticity_token", '1212 ...
- 上传漏洞科普[1]-文件上传表单是Web安全主要威胁
为了让最终用户将文件上传到您的网站,就像是给危及您的服务器的恶意用户打开了另一扇门.即便如此,在今天的现代互联网的Web应用程序,它是一种 常见的要求,因为它有助于提高您的业务效率.在Facebook ...
- bootstrap上传表单的时候上传的数据默认是0 一定要小心
bootstrap上传表单的时候上传的数据默认是0 一定要小心
- php上传中文文件文件名乱码问题
php上传文件是最最基础的一个技术点,但是深入进去也有不少问题需要解决,这不,上传中文文件后,文件名变成了乱码. 下面是问题代码,很简单: 1.问题代码 html部分: <html> &l ...
- php上传文件中文文件名乱码的解决方法
文件上传是我们在处理表单提交时候最常用的功能之一,今天写了一个小小的demo,如下: 先看结构: html为表单提交的页面,php为处理表单的文件,upload为上传文件所放的位置 html: < ...
- 解决swfupload上传控件文件名中文乱码问题 三种方法 flash及最新版本11.8.800.168
目前比较流行的是使用SWFUpload控件,这个控件的详细介绍可以参见官网http://demo.swfupload.org/v220/index.htm 在使用这个控件批量上传文件时发现中文文件名都 ...
- 使用ajax上传表单(带文件)
在使用form表单的时候上传文件+表单,会使得页面跳转,而在某些时候不希望跳转,只变化页面中的局部信息 通过查找资料,可以使用FormData进行ajax操作. FormData介绍:XMLHttpR ...
- 原生js封装ajax:传json,str,excel文件上传表单提交
由于项目中需要在提交ajax前设置header信息,jquery的ajax实现不了,我们自己封装几个常用的ajax方法. jQuery的ajax普通封装 var ajaxFn = function(u ...
随机推荐
- POJ3264(线段树入门题)
Balanced LineupCrawling in process... Crawling failed Time Limit:5000MS Memory Limit:65536KB ...
- ubuntu在recovery模式下更改用户密码
http://www.jb51.net/os/Ubuntu/164636.html 1, restart 2, Hold down shift key / press and hold 3, sele ...
- ie不支持的event.stopPropagation的解决方式
if (event.stopPropagation) { // 针对 Mozilla 和 Opera event.stopPropagation(); } else if (window.event) ...
- linux ip地址自动获取,ip地址…
linux ip地址自动获取,ip地址手动设置(图文解释) 2011-04-19 16:19:31| 分类: 服务器(appache/n | 标签: |字号大中小 订阅 linux ip地址自动获取( ...
- Jmeter JDBC Request 中文乱码问题
在JDBC Request的SQL Query的编辑器输入中文会乱码,导入插入数据库的内容也是乱码,如下图 解决办法:JDBC Connection Configuration的Database UR ...
- ubuntu下终于安装好了nvidia的gt540显卡驱动
ubuntu下终于安装好了nvidia的gt540显卡驱动.估计好多童鞋怕麻烦都放弃安装了哈. 先看看效果. ~$ lspci |grep -i vga :) :00.0 VGA compatible ...
- java之Date(日期)、Date格式化、Calendar(日历)
参考http://how2j.cn/k/date/date-date/346.html Date(日期) Date类 注意:是java.util.Date; 而非 java.sql.Date,此类是给 ...
- Linux 系统初始化和服务
系统的初始化和服务 1. Linux 系统启动流程 打开计算机,从主板 BIOS(Basic Input/Out System)读取其中所存储的程序,引导你找到存储系统的硬件(如光盘.硬盘等) 接下来 ...
- 线性Softmax分类器实战
1 概述 基础的理论知识参考线性SVM与Softmax分类器. 代码实现环境:python3 2 数据预处理 2.1 加载数据 将原始数据集放入"data/cifar10/"文件夹 ...
- unity2017分离动作
http://tsubakit1.hateblo.jp/entry/2015/06/01/235939 using UnityEngine; using UnityEditor; using Syst ...