- 作者:老汪软件技巧
- 发表时间:2024-08-23 00:02
- 浏览量:
三、相关代码
Resttemplate 及自定义 ClientHttpRequestInterceptor Bean 对象代码
@Bean(name = "dmsRestTemplate")
public RestTemplate restTemplate(
@Qualifier("dmsRequestInterceptor") ClientHttpRequestInterceptor dmsRequestInterceptor) {
RestTemplate restTemplate = new RestTemplate();
((AllEncompassingFormHttpMessageConverter) restTemplate.getMessageConverters().get(4))
.setMultipartCharset(StandardCharsets.UTF_8);
restTemplate.getInterceptors().add(dmsRequestInterceptor);
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return super.hasError(response.getStatusCode())
&& !HttpStatus.NOT_FOUND.equals(response.getStatusCode());
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
super.handleError(response);
}
});
return restTemplate;
}
@Bean
public ClientHttpRequestInterceptor dmsRequestInterceptor(FileStorageProperties fileStorageProperties) {
String userName = fileStorageProperties.getDms().getUserName();
String password = fileStorageProperties.getDms().getPassword();
return (request, body, execution) -> {
HttpHeaders headers = request.getHeaders();
MediaType type = MediaType.parseMediaType(MediaType.MULTIPART_FORM_DATA_VALUE);
headers.setContentType(type);
headers.setBasicAuth(userName, password, StandardCharsets.UTF_8);
return execution.execute(request, body);
};
}
文件上传代码
@Override
public FileStorageBO upload(String filePath) throws BaseAppException {
LOGGER.debug("DMSFileStorage upload by file path start.");
if (StringUtils.isEmpty(fileStorageProperties.getDms().getRestUrl())) {
LOGGER.error("DMS rest url config not exist!");
ExceptionHandler.publish("EPA-COMMON-0010", ExceptionHandler.BUSS_ERROR);
}
File tempFile = new File(filePath);
FileStorageBO result = new FileStorageBO(tempFile);
MultiValueMap postParameters = new LinkedMultiValueMap<>();
FileSystemResource resource = new FileSystemResource(tempFile.getAbsolutePath());
postParameters.add("file", resource);
postParameters.add("shardingkey", "EPA_" + getShardingKey());
HttpEntity> httpEntity = new HttpEntity<>(postParameters);
try {
String dmsId = dmsRestTemplate.postForObject(fileStorageProperties.getDms().getRestUrl() + "/file",
httpEntity, String.class);
result.setFileIdentity(dmsId);
LOGGER.debug("DMSFileStorage upload by file path end. dms id is {}", dmsId);
}
catch (RestClientException e) {
LOGGER.error(e);
ExceptionHandler.publish("EPA-COMMON-0011", ExceptionHandler.BUSS_ERROR, e.getLocalizedMessage());
}
return result;
}
四、问题原因
拦截器中设置 ContentType 为 multipart/form-data 时,无法自动生成 boundary 信息,导致无法根据该分隔符信息来解析请求体
在使用multipart/form-data格式发送HTTP请求时,请求体的数据会被分割成多个部分,每个部分之间使用一个特定的分隔符(boundary)进行分隔。这个boundary是在Content-Type头部中指定的,用于告诉服务器如何识别每个部分的开始和结束。
当使用RestTemplate发送multipart/form-data请求时,RestTemplate会自动处理boundary的生成和添加到请求的Content-Type头部中。这样服务器就能够正确解析请求体中的各个部分。
使用RestTemplate构建multipart/form-data请求时,只需设置正确的Content-Type为multipart/form-data,RestTemplate会负责生成请求体的各个部分,并在Content-Type头部中添加正确的boundary信息。
不需要手动追加boundary到请求体中,RestTemplate会在内部处理这一细节,确保请求能够正确地被服务器解析。
因此,使用RestTemplate发送multipart/form-data请求时,只需设置正确的Content-Type为multipart/form-data,RestTemplate会负责处理boundary的生成和添加,确保请求能够正确发送到服务器并被正确解析。
通常情况下,Content-Type的设置应该由发送请求的代码负责,而不是在ClientHttpRequestInterceptor中进行设置。ClientHttpRequestInterceptor主要用于在发送请求之前或之后对请求进行修改或处理,例如添加认证信息、日志记录、错误处理等。
六、问题修复
将 ContentType 移到上传代码中
拦截器 Bean:
@Bean
public ClientHttpRequestInterceptor dmsRequestInterceptor(FileStorageProperties fileStorageProperties) {
String userName = fileStorageProperties.getDms().getUserName();
String password = fileStorageProperties.getDms().getPassword();
return (request, body, execution) -> {
HttpHeaders headers = request.getHeaders();
headers.setBasicAuth(userName, password, StandardCharsets.UTF_8);
return execution.execute(request, body);
};
}
上传代码:
@Override
public FileStorageBO upload(String filePath) throws BaseAppException {
LOGGER.debug("DMSFileStorage upload by file path start.");
if (StringUtils.isEmpty(fileStorageProperties.getDms().getRestUrl())) {
LOGGER.error("DMS rest url config not exist!");
ExceptionHandler.publish("EPA-COMMON-0010", ExceptionHandler.BUSS_ERROR);
}
File tempFile = new File(filePath);
FileStorageBO result = new FileStorageBO(tempFile);
MultiValueMap postParameters = new LinkedMultiValueMap<>();
FileSystemResource resource = new FileSystemResource(tempFile.getAbsolutePath());
postParameters.add("file", resource);
postParameters.add("shardingkey", "EPA_" + getShardingKey());
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType(MediaType.MULTIPART_FORM_DATA_VALUE);
headers.setContentType(type);
HttpEntity> httpEntity = new HttpEntity<>(postParameters, headers);
try {
String dmsId = dmsRestTemplate.postForObject(fileStorageProperties.getDms().getRestUrl() + "/file",
httpEntity, String.class);
result.setFileIdentity(dmsId);
LOGGER.debug("DMSFileStorage upload by file path end. dms id is {}", dmsId);
}
catch (RestClientException e) {
LOGGER.error(e);
ExceptionHandler.publish("EPA-COMMON-0011", ExceptionHandler.BUSS_ERROR, e.getLocalizedMessage());
}
return result;
}