java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Resttemplate上传文件500

Resttemplate上传文件500异常的原因及解决方法

作者:NullInfo

使用 Resttemplate 调用 DMS 文件服务器 Http 接口,出现 500 异常报错,所以本文给大家介绍了Resttemplate上传文件500异常的原因及解决方法,需要的朋友可以参考下

一、问题背景

使用 Resttemplate 调用 DMS 文件服务器 Http 接口,出现 500 异常报错

二、问题描述

通过 ClientHttpRequestInterceptor 拦截器设置 ContentType 和 BasicAuth 后,调用DMS 文件服务器 Http 接口,出现 500 异常报错

三、相关代码

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<String, Object> postParameters = new LinkedMultiValueMap<>();
    FileSystemResource resource = new FileSystemResource(tempFile.getAbsolutePath());
    postParameters.add("file", resource);
    postParameters.add("shardingkey", "EPA_" + getShardingKey());
    HttpEntity<MultiValueMap<String, Object>> 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-Typemultipart/form-dataRestTemplate会负责生成请求体的各个部分,并在Content-Type头部中添加正确的boundary信息。

不需要手动追加boundary到请求体中,RestTemplate会在内部处理这一细节,确保请求能够正确地被服务器解析。

因此,使用RestTemplate发送multipart/form-data请求时,只需设置正确的Content-Typemultipart/form-dataRestTemplate会负责处理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<String, Object> 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<MultiValueMap<String, Object>> 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;
}

以上就是Resttemplate上传文件500异常的原因及解决方法的详细内容,更多关于Resttemplate上传文件500的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文