springcloud环境下springboot 上传中文名文件乱码问题

springcloud环境下springboot 上传中文名文件乱码问题

背景

由于同事前两天在做文件上传时,测试中文名文件上传后,后端获取到的文件名称为???.png,刚开始以为是前端编码问题,则排查后发现前后端均使用的是utf-8编码格式;在几次修改不同获取文件名方式后,还是存在文件名乱码问题,最终在本地用postman测试后发现,直接调用上传图片的模块,是不会出现这样的问题的;但是从对外接口模块上传图片则会出现文件名乱码问题,对外接口是通过网关进入的,猜测会不会是网关配置等问题导致,查资料后发现可能是zuul的问题导致。

文件名乱码

SpringCloud环境下Springboot 上传文件时, 中文文件名会出现乱码,文件名变成问号。但是,如果不通过网关zuul,上传文件就不会乱码,因此猜测是Zuul对上传的请求的编码进行了处理,最终在网上找到了两种解决方案。

原理

Spring Cloud Zuul现在对于上传文件有两种处理方式,一种是用spring mvc,另一种是zuulServlet。spring mvc对文件处理不是很好,会导致乱码问题,zuulServlet则不会。

在zuul的过滤器中,有一个pre的过滤器 ServletDetectionFilter,他的执行顺序是-3,也是最先执行的过滤器,在这个过滤器中,有这么一段代码:


@Override
public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
    if (!(request instanceof HttpServletRequestWrapper) 
            && isDispatcherServletRequest(request)) {
        ctx.set(IS_DISPATCHER_SERVLET_REQUEST_KEY, true);
    } else {
        ctx.set(IS_DISPATCHER_SERVLET_REQUEST_KEY, false);
    }
 
    return null;
}

在这个方法中,IS_DISPATCHER_SERVLET_REQUEST_KEY为false就会用ZuulServlet处理。如果没加/zuul前缀,IS_DISPATCHER_SERVLET_REQUEST_KEY就会置为true,就会用spring mvc上传。会出现乱码问题。

一般情况下,发送到API网关的外部请求都会被Spring的DispatcherServlet处理,除了通过/zuul/路径访问的请求会绕过DispatcherServlet,被ZuulServlet处理,主要用来应对处理大文件上传的情况。

处理方式

方案一:
在上传文件的请求路径之前添加字符串“zuul”声明此请求的编码不做处理。
例如在当前代码下,请求路径是:

localhost:9090/pay/uploadFile

那么采用方案一解决中文乱码的请求路径就是:

localhost:9090/zuul/pay/uploadFile

方案二:
在方案一的基础上,需要将前端代码的请求地址进行修改,如果地址固定死无法进行修改时,可以通过在zuul的配置文件中添加一个如下的属性:

zuul.servlet-path=/

注意是在网关的配置文件中添加。

总结

排查问题要找准问题发生的准确位置,刚开始没有定位到位置,以为是程序编码问题,排查后发现不是,后面还以为是springboot临时文件目录的编码问题,排查后发现还不是,最后根据postman访问对外接口与直接访问上传图片的模块后,才发现可能是Spring Cloud Zuul现在对于上传文件两种处理方式不同导致。所以解决问题前,一定要先准确定位问题。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值