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上传表单文件名乱码的更多相关文章

  1. 【Flask】 结合wtforms的文件上传表单

    表单中的文件上传 基本的表单渲染,表单类设置等等就不多说了,参看另一个文章即可.但是那篇文章里没有提到对于FileField,也就是上传文件的表单字段是如何处理,后端又是如何实现接受上传过来的文件的. ...

  2. ajax上传表单的俩种方式

    1.用h5对象上传表单(图片) var formData = new FormData(); formData.append("authenticity_token", '1212 ...

  3. 上传漏洞科普[1]-文件上传表单是Web安全主要威胁

    为了让最终用户将文件上传到您的网站,就像是给危及您的服务器的恶意用户打开了另一扇门.即便如此,在今天的现代互联网的Web应用程序,它是一种 常见的要求,因为它有助于提高您的业务效率.在Facebook ...

  4. bootstrap上传表单的时候上传的数据默认是0 一定要小心

    bootstrap上传表单的时候上传的数据默认是0 一定要小心

  5. php上传中文文件文件名乱码问题

    php上传文件是最最基础的一个技术点,但是深入进去也有不少问题需要解决,这不,上传中文文件后,文件名变成了乱码. 下面是问题代码,很简单: 1.问题代码 html部分: <html> &l ...

  6. php上传文件中文文件名乱码的解决方法

    文件上传是我们在处理表单提交时候最常用的功能之一,今天写了一个小小的demo,如下: 先看结构: html为表单提交的页面,php为处理表单的文件,upload为上传文件所放的位置 html: < ...

  7. 解决swfupload上传控件文件名中文乱码问题 三种方法 flash及最新版本11.8.800.168

    目前比较流行的是使用SWFUpload控件,这个控件的详细介绍可以参见官网http://demo.swfupload.org/v220/index.htm 在使用这个控件批量上传文件时发现中文文件名都 ...

  8. 使用ajax上传表单(带文件)

    在使用form表单的时候上传文件+表单,会使得页面跳转,而在某些时候不希望跳转,只变化页面中的局部信息 通过查找资料,可以使用FormData进行ajax操作. FormData介绍:XMLHttpR ...

  9. 原生js封装ajax:传json,str,excel文件上传表单提交

    由于项目中需要在提交ajax前设置header信息,jquery的ajax实现不了,我们自己封装几个常用的ajax方法. jQuery的ajax普通封装 var ajaxFn = function(u ...

随机推荐

  1. javacpp-FFmpeg系列之3: 像素图像数据转换(BGR与BufferdImage互转,RGB与BufferdImage互转,BufferdImage转Base64编码)

    javacpp-ffmpeg系列: javacpp-FFmpeg系列之1:视频拉流解码成YUVJ420P,并保存为jpg图片 javacpp-FFmpeg系列之2:通用拉流解码器,支持视频拉流解码并转 ...

  2. 使用webdriver出现的问题:[18796:1808:0730/131103.313:ERROR:install_util.cc(600)] Failed to read HKLM\SOFTWARE\Policies\Google\Chrome\MachineLevelUserCloudPolicyEnrollmentToken: 系统找不到指定的文件。 (0x2) DevTools lis

    1.注册表导致 [5956:4996:0710/155156.898:ERROR:install_util.cc(589)] Unable to create registry key HKLM\SO ...

  3. 使用Netty实现的一个简单HTTP服务器

    1.HttpServer,Http服务启动类,用于初始化各种线程和通道 public class HttpServer { public void bind(int port) throws Exce ...

  4. 【转】有的共享软件赚了一百万美元,而为什么你没有?&&我的软件推广成功之路

    有的共享软件赚了一百万美元,而为什么你没有? 转自:http://blog.csdn.net/wangjiwei2010/article/details/1267044 译:DreamGoal 原作: ...

  5. maven+eclpse+jmeter+jenkis

    1.maven配置:http://www.cnblogs.com/AlanLee/p/6133189.html 2.在eclipse中创建maven项目:https://jingyan.baidu.c ...

  6. AR/VR-VR:VR

    ylbtech-AR/VR-VR:VR 虚拟现实技术是一种可以创建和体验虚拟世界的计算机仿真系统,它利用计算机生成一种模拟环境,是一种多源信息融合的.交互式的三维动态视景和实体行为的系统仿真使用户沉浸 ...

  7. gitea (git服务器), 修改配置,更换IP地址

    使用的gitea项目管理git 服务器 (可以不用备份项目, 通过直接修改gitea配置, 直接使用) 步骤1 可以直接访问项目, 步骤2 ,如果已有项目IP地址固定为192.168.1.x, 新的I ...

  8. POJ-3050

    Hopscotch Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4385   Accepted: 2924 Descrip ...

  9. 面试题: 数据库 sql优化 sql练习题 有用 学生表,课程表,成绩表,教师表 练习

    什么是存储过程?有哪些优缺点? 什么是存储过程?有哪些优缺点? 存储过程就像我们编程语言中的函数一样,封装了我们的代码(PLSQL.T-SQL). 存储过程的优点: 能够将代码封装起来 保存在数据库之 ...

  10. Poll:&nbsp;Most&nbsp;Americans&amp;n…

    Most Americans support tough new measures to counter gun violence, including banning assault weapons ...