No converter for [class java.util.LinkedHashMap] with preset Content-Type ‘application/vnd.ms-excel;

通常解决方案参考
https://blog.youkuaiyun.com/qq_42651201/article/details/120710224

我的报错 

org.springframework.http.converter.HttpMessageNotWritableException:
 No converter for [class com.xxx.dto.Result] with preset Content-Type 'application/vnd.ms-excel;charset=utf-8'

我的问题根因

controller处理逻辑有问题,导致报错,然后被全局异常捕捉,再然后返回了错误信息

也就是说本来没有返回值的方法,最终有返回值class com.xxx.dto.Result ,就会抛出以上错误。

我的解决方案

把controller里面的报错解决,让逻辑正常执行,不报错,不被全局异常捕捉即可

以上为我遇到的问题根因和解决方案

另外还有种情况 也可能会报以上错误,就是表格列的  index的值重复

@ExcelProperty(value = "字段", index = 0)

以下是具体的分析步骤,可看,可略过。

我的代码情况:
1. controller内无返回值,因此不适用通常解决方案

public void downloadExt(HttpServletResponse response, DataQuery qry) throws IOException {
    try {
        // 查询数据 导出数据逻辑
    } catch (Exception e) {
            throw new BsException("文件下载失败");
    }
}


2. 再细看日志,报错内其他信息

org.springframework.http.converter.HttpMessageNotWritableException:
 No converter for [class com.xxx.dto.Result] with preset Content-Type 'application/vnd.ms-excel;charset=utf-8'


发现虽然接口代码没有返回值,但是 前端请求接口的时候 的确返回了 com.xxx.dto.Result 对象

3. 查看代码是否有全局异常处理

public class ExceptionHandler  implements GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Result errorException(Exception e) {
        log.error(e.getMessage(), e);
        return Result.fail(xxxx);
    }
 }


经查看,是全局异常处理捕捉了第1步的controller抛出的异常,然后返回了Result对象,导致下载报错。

但是 根因不在这里,而是在导出的controller代码里面报错了
public void downloadExt(HttpServletResponse response, DataQuery qry) throws IOException {
    try {
        **// 查询数据 导出数据逻辑**
    } catch (Exception e) {
            log.info(null, e);
            throw new BsException("文件下载失败");
    }
}

打出日志,查看日志,即可解决问题


 

在 Spring Boot 应用中,当控制器方法返回一个 `LinkedHashMap` 对象,并且尝试将其直接写入响应体时(例如通过 `@ResponseBody` 或 `ResponseEntity`),Spring 会尝试找到合适的 `HttpMessageConverter` 来处理该对象并将其序列化为请求方期望的格式。如果目标 Content-Type 是 `application/vnd.ms-excel`,而实际返回的是一个 `LinkedHashMap`,就会出现如下异常: ``` No converter found for return value of type: class java.util.LinkedHashMap and content type application/vnd.ms-excel ``` 这个错误表明 Spring 没有能够将 `LinkedHashMap` 转换为指定 MIME 类型的响应内容。以下是几个可能的原因和解决方案。 --- ### 原因分析 1. **不匹配的响应类型与内容类型** Spring 的默认 `HttpMessageConverter` 实现(如 `Jackson2JsonMessageConverter`)可以很好地处理 JSON 数据(`application/json`)。然而,当设置的 Content-Type 为 `application/vnd.ms-excel` 时,Spring 不会使用 JSON 转换器来处理数据,因为该类型通常用于 Excel 文件流(即二进制数据)[^1]。 2. **未配置自定义转换器** 如果希望将 `LinkedHashMap` 转换为 Excel 文件(`.xls` 或 `.xlsx` 格式),需要显式地编写一个自定义的 `HttpMessageConverter`,或者在控制器中手动构造 Excel 文件流作为响应。 3. **依赖缺失或配置问题** 确保项目中包含 Jackson 和 Spring Web 的相关依赖,以支持常见的数据格式转换。如果这些依赖未正确引入,也可能导致没有可用的转换器。 --- ### 解决方案 #### 1. 修改响应内容类型为 `application/json` 如果你只是想返回结构化的数据而不是真正的 Excel 文件,应将响应的 Content-Type 设置为 `application/json`。这样 Spring 会自动使用 `Jackson2JsonMessageConverter` 来处理 `LinkedHashMap`。 ```java @RequestMapping("/upload") @ResponseBody public LinkedHashMap<String, Object> handleUpload() { LinkedHashMap<String, Object> response = new LinkedHashMap<>(); response.put("status", "success"); response.put("data", "file uploaded"); return response; } ``` #### 2. 手动构建 Excel 文件流 如果你确实需要返回 Excel 文件,可以使用 Apache POI 或其他库来生成 Excel 文件,并将字节流写入响应体。此时应避免直接返回 `LinkedHashMap`。 ```java @GetMapping(value = "/download", produces = "application/vnd.ms-excel") public void downloadExcel(HttpServletResponse response) throws IOException { Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Data"); Row headerRow = sheet.createRow(0); Cell headerCell = headerRow.createCell(0); headerCell.setCellValue("Key"); headerCell = headerRow.createCell(1); headerCell.setCellValue("Value"); Row dataRow = sheet.createRow(1); dataRow.createCell(0).setCellValue("status"); dataRow.createCell(1).setCellValue("success"); response.setContentType("application/vnd.ms-excel"); response.setHeader("Content-Disposition", "attachment; filename=data.xlsx"); try (OutputStream out = response.getOutputStream()) { workbook.write(out); } } ``` #### 3. 自定义 `HttpMessageConverter`(高级) 如果你希望 Spring 能够自动将 `LinkedHashMap` 转换为 Excel 文件,可以通过实现 `AbstractHttpMessageConverter` 并注册到 Spring MVC 配置中。这适用于需要统一处理所有 Excel 输出的场景。 ```java public class ExcelMessageConverter extends AbstractHttpMessageConverter<LinkedHashMap<String, Object>> { @Override protected boolean supports(Class<?> clazz) { return LinkedHashMap.class.isAssignableFrom(clazz); } @Override protected LinkedHashMap<String, Object> readInternal(Class<? extends LinkedHashMap<String, Object>> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { // 可选:读取 Excel 文件并转换为 LinkedHashMap return null; } @Override protected void writeInternal(LinkedHashMap<String, Object> body, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Data"); int rowNum = 0; for (Map.Entry<String, Object> entry : body.entrySet()) { Row row = sheet.createRow(rowNum++); row.createCell(0).setCellValue(entry.getKey()); row.createCell(1).setCellValue(entry.getValue().toString()); } try (OutputStream out = outputMessage.getBody()) { workbook.write(out); } } } ``` 然后,在配置类中注册该转换器: ```java @Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters, MediaType mediaType) { if (mediaType.includes(MediaType.parseMediaType("application/vnd.ms-excel"))) { converters.add(new ExcelMessageConverter()); } } } ``` --- ### 总结 - 如果你不需要真正输出 Excel 文件,请确保返回的内容类型是 `application/json`。 - 如果需要输出 Excel 文件,应手动构造文件流并设置正确的 Content-Type- 对于更复杂的场景,可考虑实现自定义 `HttpMessageConverter`。 ---
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值