spring 文件上传乱码问题

本文深入探讨了在使用Spring Cloud Zuul时遇到的文件上传中文乱码问题,分析了问题产生的根本原因在于请求解码与编码过程中的不一致性,并提供了两种有效的解决方案:通过在API接口前添加/zuul前缀或修改zuul配置文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近开发中遇到了一个文件上传乱码问题,经过一顿百度谷歌以后,解决了问题以后,现在把这个问题的前世今生都记录下。

一、问题描述

从前端上传文件后,后端接受到文件,显示文件名

//此时name=????全是问号,还非乱码
String name = multipartFile.getOriginalFilename(); 

二、问题原因分析

为什么会出现乱码?因为请求时,网关会先对请求进行解码,以便它们可用Zuul过滤器的可能修改,然后在过滤器构建过程后重新对请求进行编码,重新编码的过程由于编码不一致导致乱码。
在这里插入图片描述
在ServletDetectionFilter过滤中
Spring Cloud Zuul现在对于上传文件有两种处理方式,一种是用spring mvc,另一种是zuulServlet。spring mvc对文件处理不是很好,会导致乱码问题,zuulServlet则不会。
在zuul的过滤器中,有一个pre的过滤器 ServletDetectionFilter,他的执行顺序是-3,也是最先执行的过滤器,在这个过滤器中,有这么一段代码:

/*
 * Copyright 2013-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.cloud.netflix.zuul.filters.pre;

import javax.servlet.http.HttpServletRequest;

import org.springframework.cloud.netflix.zuul.util.RequestUtils;
import org.springframework.web.servlet.DispatcherServlet;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.HttpServletRequestWrapper;
import com.netflix.zuul.http.ZuulServlet;

/**
 * Detects whether a request is ran through the {@link DispatcherServlet} or {@link ZuulServlet}.
 * The purpose was to detect this up-front at the very beginning of Zuul filter processing
 *  and rely on this information in all filters.
 *  RequestContext is used such that the information is accessible to classes 
 *  which do not have a request reference.
 * @author Adrian Ivan
 */
public class ServletDetectionFilter extends ZuulFilter {

	public ServletDetectionFilter() {
	}

	@Override
	public String filterType() {
		return "pre";
	}

	/**
	 * Must run before other filters that rely on the difference between 
	 * DispatcherServlet and ZuulServlet.
	 */
	@Override
	public int filterOrder() {
		return -3;
	}

	@Override
	public boolean shouldFilter() {
		return true; 
	}

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

		return null;
	}
	
    private boolean isDispatcherServletRequest(HttpServletRequest request) {
        return request.getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null;
    }     	

}

以下是常量定义代码

public class RequestUtils {
    
    public static final String IS_DISPATCHERSERVLETREQUEST = "isDispatcherServletRequest";
    
    public static boolean isDispatcherServletRequest() {
        return RequestContext.getCurrentContext().getBoolean(IS_DISPATCHERSERVLETREQUEST);
    }
    
    public static boolean isZuulServletRequest() {
        //extra check for dispatcher since ZuulServlet can run from ZuulController
        return !isDispatcherServletRequest() && RequestContext.getCurrentContext().getZuulEngineRan();
    }    
}

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

三、解决办法

第一种解决方案,api接口前面 /zuul:
在不修改zuul默认配置参数的情况下,在上传文件的请求路径之前添加字符串“zuul”声明此请求被ZuulServlet处理。
例如在当前代码下,请求路径是:
localhost:8080/up/upload
那么采用方案一解决中文乱码的请求路径就是:
localhost:8080/zuul/up/upload
经过测试,中文乱码问题成功解决。
如果第一种方式,显示404,尝试第二种解决方案,改zuul的配置文件:
在zuul的配置文件中添加一个如下的属性:
zuul.servlet-path=/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

善守的大龙猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值