防止Spring的RestTemplate为multipart

防止Spring的RestTemplate为multipart

本文介绍了防止Spring的RestTemplate为multipart/form-data中的每个参数添加标头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须使用Spring的 RestTemplate 来调用一个外部API,该API接受带有 Content-Type:multipart/form-data 的POST请求.输入数据只是键值,没有附件,但服务器强制我使用 multipart/form-data .

I have to use Spring's RestTemplate to call an external API that takes a POST request with Content-Type: multipart/form-data. The input data are only key-values, no attachments but the server enforce me the use multipart/form-data.

以下是可以正常工作的原始请求.

Following is the raw request that works fine.

POST http://the-api:8080 HTTP/1.1
Content-Type: multipart/form-data; boundary=--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL
Accept: */*
Host: the-api:8080
accept-encoding: gzip, deflate
content-length: 680
Connection: keep-alive

--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL
Content-Disposition: form-data; name="param1"

value1
--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL
Content-Disposition: form-data; name="param2"

value2
--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL--

以下是我从RestTemplate的日志中提取并重新排列的原始请求,该请求不起作用,因为服务器将标头误认为该值.

Following is the raw request that I extracted and rearranged from the log of the RestTemplate, it did not work because the server mistook the header for the value.

POST http://the-api:8080 HTTP/1.1
Content-Type: multipart/form-data; boundary=--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL
Accept: */*
Host: the-api:8080
accept-encoding: gzip, deflate
content-length: 680
Connection: keep-alive

--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL
Content-Disposition: form-data; name="param1"
Content-Type: text/plain;charset=UTF-8
Content-Length: 29

value1
--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL
Content-Disposition: form-data; name="param2"
Content-Type: text/plain;charset=UTF-8
Content-Length: 14

value2
--Eh0oKOHPOSEIJTzFevDxHhPNKhQl7AP6kQL--

以下是代码

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("param1", "value1);
params.add("param2", "value2);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);

URI uri = UriComponentsBuilder.fromHttpUrl("http://the-api:8080")
        .build().encode(Charset.forName("UTF-8")).toUri();

return restTemplate.postForObject(uri, request, KKPMailResponse.class);

问题

如何防止Spring的RestTemplate为每个参数自动添加标题 Content-Type:text/plain; charset = UTF-8 Content-Length:xx /p>

推荐答案

我没有找到阻止Spring生成条目的方法,但是您可以在发送请求之前使用拦截器将其删除.为此,您必须按如下所述在拦截器中操作请求正文:

I didn't find a way to prevent Spring from generating the entries, but you can use an interceptor to remove them before sending the request. For that you have to manipulate the request body in the interceptor as follows:

public class MultiPartFormDataCleaningInterceptor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        final MediaType contentType = request.getHeaders().getContentType();
        if (contentType != null
                && MediaType.MULTIPART_FORM_DATA.getType().equals(contentType.getType())
                && MediaType.MULTIPART_FORM_DATA.getSubtype().equals(contentType.getSubtype())) {
            return execution.execute(request, stripContentTypeAndLength(body));
        }
        return execution.execute(request, body);
    }

    private byte[] stripContentTypeAndLength(byte[] body) {
        final String bodyStr = new String(body);
        final StringBuilder builder = new StringBuilder();
        try (final Scanner scanner = new Scanner(bodyStr)) {
            while (scanner.hasNextLine()) {
                final String line = scanner.nextLine();
                if (!line.startsWith("Content-Type:")
                        && !line.startsWith("Content-Length:")) {
                    builder.append(line).append("\r\n");
                }
            }
        }
        final String newBodyStr = builder.toString();
        return newBodyStr.getBytes();
    }
}

这篇关于防止Spring的RestTemplate为multipart/form-data中的每个参数添加标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 05:23