使用RestTemplate 发送 multipart/form-data 时中文乱码【???】怎么解决?

 背景:

我使用的是grails框架,里面集成了spring 全家桶,我需要与另一个系统交互文件以及描述文件的文本内容。使用的RestTemplate进行交互。


 问题描述:

restTemplate中使用multipart/form-data 类型的时候,远程服务器接收到的中文是乱码:【???】,在网上也看了很多文章,一直没有解决。

思路与原因探究

既然确定了是restTemplate调用产生的乱码,通过从网上检索的各种资料不难想到是MessageConverter导致的问题,网上使用较多的解决思路主要有以下两种:

设置StringHttpMessageConverter的编码为UTF-8,StringHttpMessageConverter的默认编码为ISO-8859-1,即:

如果参数均为String类型,这样设置是有用的,对于我的问题,可以看到在代码中已经进行了设置,但是仍然存在乱码问题
在HttpHeader中设置Content-Type的编码为UTF-8,类似如下代码:

其实网上并没有对于multipartFormData设置编码的例子,这里我稍微尝试了一下,不起作用
找到引发问题的本质原因
用debug 断点step by step对restTemplate.postForEntity的请求进行追踪:

进入doWithRequest方法的实现查看

进入writeParts方法查看

进入writePart方法

查看this.partConverters的值,从而查看StringHttpMessageConverter的编码情况

我们回过头看一看this.partConverters的初始化赋值情况,可以看到他默认给我们调用的是StringHttpMessageConverter()无参构造方法,我们可以点进去看看无参构造方法正好有个默认编码就是ISO-8859-1;

查看StringHttpMessageConverter的无参构造函数

由此我们已经找出混合类型参数传输时乱码的原因所在。


解决方案

利用FormHttpMessageConverter提供的setPartConvetrters方法替换默认的partConverters,然后再替换restTemplate中原先的FormHttpMessageConverter,这里需要我们自动构建一下RestTemplate一下是创建代码:  在自己创建converters 时一定要把

new AllEncompassingFormHttpMessageConverter()注释调,这个方法是会处理mutipart表单类型的数据的,而且选择转换器的时候是优先选择我们自己创建的FormHttpMessageConerter放在了后面就会用不到,因为优先使用原则。
 
private static RestTemplate createRestTemplate() {
        RestTemplate restTemplate = new RestTemplate()
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory()
        requestFactory.setConnectTimeout(5000)  // 连接超时时间(毫秒)
        requestFactory.setReadTimeout(5000)  // 读取超时时间(毫秒)
        restTemplate.setRequestFactory(requestFactory)
        List<HttpMessageConverter<?>> converters = new ArrayList<>()
        converters.add(new ByteArrayHttpMessageConverter())
        converters.add(new ResourceHttpMessageConverter())
        converters.add(new SourceHttpMessageConverter<Source>())
//        converters.add(new AllEncompassingFormHttpMessageConverter())
        converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8))
        FormHttpMessageConverter formConverter = new FormHttpMessageConverter()
        formConverter.setPartConverters(converters)
        formConverter.setCharset(StandardCharsets.UTF_8)
        converters.add(formConverter)
        restTemplate.setMessageConverters(converters)
        return restTemplate
    }

以下是接口调用时代码:

static def sendReport(String token, LinkedMultiValueMap form) {
        def headers = new HttpHeaders()

        headers.setContentType(new MediaType("multipart", "form-data", StandardCharsets.UTF_8))
        headers.set("Authorization", "Bearer " + token)
        def restTemplate = createRestTemplate()
        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(form, headers)

        try {
//            ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://localhost:8080/pmlis/pathologyOrders/testUpload2Image", entity, String.class)
            ResponseEntity<String> responseEntity = restTemplate.postForEntity(Util.IMAGE_MANAGEMENT_PLATFORM_SENDREPORT_URL, entity, String.class)

            if (responseEntity.getStatusCode().is2xxSuccessful()) {

                return true
            } else {
                String responseBody = responseEntity.getBody()
                def jsonSlurper = new JsonSlurper()
                def result = jsonSlurper.parseText(responseBody)

                throw new RuntimeException("Send report fail ${result}")
                // 处理失败情况
                // 根据 result.code 和 result.msg 进行相应的错误处理
            }
        } catch (Exception e) {
            throw new RuntimeException("send a request fail ,that cuase:${e}")

        }


    }

  • 16
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值