vue axios采用formdata传参后端springboot接收中文乱码解决办法

一、问题:

前端代码:

// 新建form表单
// this.lessonName是个字符串名字,this.upath是一份文档
// 请求头的编码格式为:Content-Type: multipart/form-data
const fd = new FormData()
fd.append('lessonName', this.lessonName)
fd.append('file', this.upath)
this.$http.post('/simulation/lesson/add1', fd).then(res => {
    if (res) {
        this.$message.success(res.data.msg)
        this.load();
        this.dialogFormVisible = false;
        this.clearFile();
    } else {
        this.$message.error(res.data.msg)
    }
})

后端代码:

// 接收函数编写。此时接收的文件file可以正常使用,但lessonName显示为乱码
// 原因是:formdata传递参数,参数会被二进制化。后端接收的时候默认格式为iso_8859_1
// 这是因为StringHttpMessageConverter读和写的编码方式是:ISO-8859-1
@PostMapping( "/add")
public ResultVO add(@RequestPart(value = "lessonName") String lessonName,
                     @RequestParam(value = "file", required = false) MultipartFile file)
{

    if (simulationLessonService.valLessonName(lessonName)){
        return new ResultVO(ResStatus.NO,"课程名已存在",false);
    }
    SimulationLessonDTO lessonDTO = new SimulationLessonDTO();
    lessonDTO.setLessonName(lessonName);
……

解决思路

1,前端传参时写明编码格式;

2,前端传参时先进行编码再传递;

3,后端接收时采用全局设置参数;

4,后端修改tomcat配置;

5,后端修改Servlet配置;

6,后端编写全局过滤器,设置request请求编码格式;

7,局部修改,硬解码。

根据上面的思路,做了一些测试。最后有两条成功办法。有些思路没有测,毕竟只是做项目,不是做科研。先说说失败的方法,后附两条成功的方法。

失败方法:

1,springboot配置文件(失败)

# 服务器配置
server:
  servlet:
    encoding:
      charset: utf-8
      enabled: true
      force: true
  tomcat:
    uri-encoding: UTF-8

2,声明接收格式(失败)

@PostMapping(value = "/add",produces = "text/plain;charset=UTF-8")

3,在jwtfilter中修改request接收参数格式(失败)

@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
    httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
    httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
    httpServletRequest.setCharacterEncoding("UTF-8");
    // 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态
    if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
        httpServletResponse.setStatus(HttpStatus.OK.value());
        return false;
    }
    return super.preHandle(request, response);
}

4,编写全局过滤器(失败)

//字符编码过滤器
@WebFilter(urlPatterns = "/*",filterName = "CharacterEncodingFilter")
public class CharacterEncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        filterChain.doFilter(request , response);
    }
    @Override
    public void destroy() {
    }
}

成功方法:

1,硬改接收参数编码(成功,但不是全局的,仅能解决燃眉之急)

 @PostMapping( "/add1")
public ResultVO add1(@RequestPart(value = "lessonName") String lessonName1,
                     @RequestParam(value = "file", required = false) MultipartFile file) 
{
    String lessonName = new String(lessonName1.getBytes(StandardCharsets.ISO_8859_1));
    if (simulationLessonService.valLessonName(lessonName)){
        return new ResultVO(ResStatus.NO,"课程名已存在",false);
    }
    SimulationLessonDTO lessonDTO = new SimulationLessonDTO();
    lessonDTO.setLessonName(lessonName);
    ……

2,编写全局编码转换器(成功,最终采用的也是这个)

/**
 * 中文乱码解决
 */
@Configuration
public class CharsetConfig extends WebMvcConfigurerAdapter {
    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
        StringHttpMessageConverter converter = new StringHttpMessageConverter(
                Charset.forName("UTF-8"));
        return converter;
    }
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.configureMessageConverters(converters);
        converters.add(responseBodyConverter());
    }
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(false);
    }
}

因为WebMvcConfigurerAdapter已被springboot弃用,根据网上查找,将WebMvcConfigurerAdapter更改为WebMvcConfigurationSupport,修改后代码为:

/**
 * 中文乱码解决
 */
@Configuration
public class CharsetConfig extends WebMvcConfigurationSupport {
    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
        StringHttpMessageConverter converter = new StringHttpMessageConverter(
                Charset.forName("UTF-8"));
        return converter;
    }
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.configureMessageConverters(converters);
        converters.add(responseBodyConverter());
    }
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(false);
    }
}

其它办法,未测试

1(思路应该是一样的),

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for(HttpMessageConverter httpMessageConverter:converters){
            if(StringHttpMessageConverter.class.isAssignableFrom(httpMessageConverter.getClass())){
                ((StringHttpMessageConverter)httpMessageConverter).setDefaultCharset(Charset.forName("UTF-8"));
            }
        }
    }
}

2,前端转换下格式(没测试,就不具体写了)

原因解析:

子类StringHttpMessageConverter

public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {

    //转成字符串的默认编码为ISO-8859-1
    public static final Charset DEFAULT_CHARSET = StandardCharsets.ISO_8859_1;

    public StringHttpMessageConverter() {
        this(DEFAULT_CHARSET);
    }
    //默认支持的MediaType是text/plain,”*/*“
    // 因为它支持MediaType.TEXT_PLAIN, MediaType.ALL所有类型,所以你的contentType无所谓~~~ 它都能够处理
    public StringHttpMessageConverter(Charset defaultCharset) {
        super(defaultCharset, MediaType.TEXT_PLAIN, MediaType.ALL);
    }


   //如果是string类型,就进入
    @Override
    public boolean supports(Class<?> clazz) {
        return String.class == clazz;
    }

    @Override
    protected String readInternal(Class<? extends String> clazz, HttpInputMessage inputMessage) throws IOException {
        Charset charset = getContentTypeCharset(inputMessage.getHeaders().getContentType());
        /// 根据编码把字符串读进来~
        return StreamUtils.copyToString(inputMessage.getBody(), charset);
    }

    @Override
    protected Long getContentLength(String str, @Nullable MediaType contentType) {
        Charset charset = getContentTypeCharset(contentType);
        return (long) str.getBytes(charset).length;
    }

    @Override
    protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException {
        HttpHeaders headers = outputMessage.getHeaders();
        if (this.writeAcceptCharset && headers.get(HttpHeaders.ACCEPT_CHARSET) == null) {
            headers.setAcceptCharset(getAcceptedCharsets());
        }
        // 根据编码把字符串写进去~
        Charset charset = getContentTypeCharset(headers.getContentType());
        StreamUtils.copy(str, charset, outputMessage.getBody());
    }

Content-Typetext/plain(其实Content-Type为任何值都一样),请求体是:飒飒说,控制台输出:?????????,乱码?

这是因为StringHttpMessageConverter读和写的编码方式是:ISO-8859-1

后续

发现单独写的CharsetConfig与SwaggerConfig继承冲突了。最后合并到SwaggerConfig类里了。

@Configuration
@EnableSwagger2
@ComponentScan("com.hz.simulation")
public class SwaggerConfig implements WebMvcConfigurer {
   /**
     * 解决中文乱码问题
     * @return
     */
    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
        StringHttpMessageConverter converter = new StringHttpMessageConverter(
                Charset.forName("UTF-8"));
        return converter;
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        WebMvcConfigurer.super.configureMessageConverters(converters);
        converters.add(responseBodyConverter());
    }

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值