Spring Boot从外部URL下载文件报No converter found错误如何解决
问题解决与优化方案
报错根因
你直接把Apache HttpClient返回的EofSensorInputStream输入流作为响应体返回,Spring MVC默认没有适配该输入流实现类的消息转换器,无法完成序列化输出,因此抛出该异常。除此之外原有代码还存在资源未主动释放、响应头配置缺失、错误场景处理不规范的问题。
优化后的实现代码
import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.apache.http.HttpResponse; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import java.io.IOException; import java.io.InputStream; public ResponseEntity<InputStreamResource> downloadAsset() throws IOException { final String username = "abd"; final String password = "rewf"; String url = "https://www.clickdimensions.com/links/TestPDFfile.pdf"; String fileName = "TestPDFfile.pdf"; // 配置Basic认证,无需手动编码Base64 CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)); // try-with-resources自动释放HttpClient资源 try (CloseableHttpClient httpClient = HttpClients.custom() .setDefaultCredentialsProvider(credsProvider) .build()) { HttpGet request = new HttpGet(url); HttpResponse response = httpClient.execute(request); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == HttpStatus.OK.value()) { InputStream inputStream = response.getEntity().getContent(); // 封装输入流为Spring可识别的Resource类型 InputStreamResource resource = new InputStreamResource(inputStream); // 配置下载响应头 HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName); headers.add(HttpHeaders.CONTENT_TYPE, "application/pdf"); return ResponseEntity.ok() .headers(headers) .contentLength(response.getEntity().getContentLength()) .body(resource); } // 非200响应返回对应错误状态码 return ResponseEntity.status(statusCode).build(); } }
优化点说明
- 用Spring内置的
InputStreamResource封装外部返回的输入流,Spring自带对应消息转换器,直接解决序列化报错问题 - 内置Basic认证配置,无需手动处理Base64编码,逻辑更规范
- 使用try-with-resources语法自动释放HTTP连接相关资源,避免资源泄漏
- 补充了下载必备的响应头配置,支持浏览器直接触发文件下载,也可根据实际业务调整Content-Type值
- 错误场景直接返回对应HTTP状态码,符合接口设计语义
内容的提问来源于stack exchange,提问作者Nitin Singhal
相关产品推荐
相关产品推荐

