You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用RestTemplate获取大CSV文件报错,如何编写适配的HttpMessageConverter?

解决RestTemplate处理CSV响应的消息转换器问题

你遇到的问题是RestTemplate默认的消息转换器不支持将text/csv类型的响应映射为InputStream,需要自定义一个适配的转换器来处理这种场景。以下是具体的实现步骤:

1. 自定义CSV输入流转换器

创建一个实现HttpMessageConverter<InputStream>的转换器类,专门处理text/csv类型的响应,直接返回输入流:

import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;

public class CsvInputStreamConverter implements HttpMessageConverter<InputStream> {

    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        // 仅处理InputStream类型和text/csv响应
        return InputStream.class.isAssignableFrom(clazz) && MediaType.TEXT_CSV.includes(mediaType);
    }

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        // 无需处理写入逻辑,返回false
        return false;
    }

    @Override
    public List<MediaType> getSupportedMediaTypes() {
        // 声明支持text/csv类型
        return Collections.singletonList(MediaType.TEXT_CSV);
    }

    @Override
    public InputStream read(Class<? extends InputStream> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        // 直接返回响应的输入流,实现流式传输
        return inputMessage.getBody();
    }

    @Override
    public void write(InputStream inputStream, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        // 无需实现写入逻辑,抛出异常提示
        throw new UnsupportedOperationException("该转换器不支持写入操作");
    }
}

2. 将转换器注册到RestTemplate

在初始化RestTemplate时,把自定义转换器添加到转换器列表的最前面,确保优先匹配text/csv类型:

RestTemplate restTemplate = new RestTemplate();
// 插入到列表头部,优先使用自定义转换器
restTemplate.getMessageConverters().add(0, new CsvInputStreamConverter());

3. 修改后的完整代码

整合后的代码可以正确获取CSV响应流并写入文件,适合处理大体积文件(避免全量加载到内存):

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.web.client.RestTemplate;

public class CsvFileDownloader {
    public static void main(String[] args) {
        String fileName = "response.csv";
        File file = new File(fileName);
        Path filePath = file.toPath();

        // 假设headers已完成初始化
        HttpEntity<Object> requestEntity = new HttpEntity<>(null, headers);
        
        RestTemplate restTemplate = new RestTemplate();
        // 注册自定义CSV转换器
        restTemplate.getMessageConverters().add(0, new CsvInputStreamConverter());

        try {
            InputStream responseStream = restTemplate
                    .exchange("serviceURL/LogFile", HttpMethod.GET, requestEntity, InputStream.class)
                    .getBody();
            Files.copy(responseStream, filePath, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

额外适配说明

如果服务返回的CSV内容类型存在变种(比如text/plain或application/csv),可以修改转换器的getSupportedMediaTypes方法,添加对应类型:

import java.util.Arrays;

@Override
public List<MediaType> getSupportedMediaTypes() {
    return Arrays.asList(MediaType.TEXT_CSV, MediaType.TEXT_PLAIN, MediaType.valueOf("application/csv"));
}

内容的提问来源于stack exchange,提问作者user1346346

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 01:16:16