使用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
相关产品推荐
相关产品推荐

