当前位置: 首页 > news >正文

数据导出为Excel接口报错:java.io.IOException: UT010029: Stream is closed

在Spring框架中,开发过程中经常需要实现数据的导出功能,尤其是将数据导出为Excel文件。然而,在实现这样的功能时,可能会遇到一些意料之外的错误,比如java.io.IOException: UT010029: Stream is closed。本文将基于一个实际案例,分析这一错误的原因及解决方案。

问题分析

错误信息

java.io.IOException: UT010029: Stream is closed
at io.undertow.servlet.spec.ServletOutputStreamImpl.write(ServletOutputStreamImpl.java:138)
...

这个错误表明,在尝试向ServletOutputStream写入数据时,流已经被关闭了。通常,这种情况会在以下几种情况下发生:

  1. 手动关闭了流:在代码中显式调用了ServletOutputStream.close()
  2. 自动关闭:某些框架或组件在处理完请求后会自动关闭流。

实际原因

在Spring MVC中,当一个请求处理器(Controller方法)返回一个值时,Spring MVC会尝试将这个值作为响应体发送。然而,在文件下载的接口中,响应体通常是通过直接写入HttpServletResponse来发送的,而不是通过返回值。如果在这样的接口中添加了返回值,Spring MVC会在响应写入完成后自动关闭流,而由于我们已经通过HttpServletResponse写入了数据,这会导致流的二次关闭,从而引发Stream is closed的错误。

解决方案

修改Controller方法

原来的Controller方法如下:

@GetMapping("/exportExcel")
public R exportExcel(@RequestParam Long formId, @RequestParam String ids, HttpServletResponse response) {// 数据处理和Excel导出逻辑ExportUtil.writeExcel(response, recordsWrapper, ...);return R.success("下载成功!");
}

修改后的Controller方法应该去除返回值,直接通过HttpServletResponse发送响应:

@GetMapping("/exportExcel")
public void exportExcel(@RequestParam Long formId, @RequestParam String ids, HttpServletResponse response) {List<Map<String, Object>> data;List<Long> longIds = Func.toLongList(ids);// 获取表单配置FormEntity formEntity = formService.getById(formId);if (null == formEntity) {throw new ServiceException("未查询到表单");}// 数据处理和Excel导出逻辑try {// ... (省略数据处理代码)ExportUtil.writeExcel(response, recordsWrapper, ...);} catch (IOException e) {log.error(e.toString());}// 注意:没有返回值
}

注意事项

  1. 去除返回值:确保文件下载接口不返回任何值。
  2. 异常处理:虽然文件写入过程中可能抛出IOException,但在实际的生产环境中,通常不应该将异常信息直接返回给用户,而是通过日志记录下来。
  3. 流的使用:在使用ServletOutputStreamPrintWriter时,注意不要在代码中显式关闭它们。

结论

在Spring MVC中实现文件下载功能时,需要特别注意流的关闭时机。确保不要在Controller方法中返回任何值,而是通过HttpServletResponse直接发送响应。这样可以避免框架自动关闭流,从而引发Stream is closed的错误。希望这篇文章能够帮助你更好地理解和解决类似的问题。


http://www.mrgr.cn/news/12142.html

相关文章:

  • 【第54课】XSS跨站Cookie盗取表单劫持网络钓鱼溯源分析项目平台框架
  • Java中金蝶凭证xml转wswsvoucher对象
  • 【区块链 + 智慧文旅】虎年春节数字藏品 | FISCO BCOS应用案例
  • nlp时序模型股价预测的基本思路(持续更新)
  • Python网络爬虫模拟登录与验证解析
  • 【3.3】贪心算法-解分发糖果
  • Apache Doris 使用 CBO 和 RBO 结合的优化策略
  • 此站点的连接不安全,解决方法
  • Sentinel-1 Level 1数据处理的详细算法定义(七)
  • 基于Vue3和Node.js的完整增删改查项目实现教程:从后端封装到前端调用
  • WHAT - 通过 react-use 源码学习 React
  • 配电房挂轨机器人巡检系统的主要优点包括
  • 足球数据分析-基于机器学习的足球比赛角球数预测模型构建
  • 前端:html+css:伪类画箭头(实心)
  • 中资优配:金融审计进入“主审+参审”新模式
  • 使用go实现TCP服务器
  • 【算法进阶2-动态规划】最长公共子序列、欧几里得算法-分数、RSA算法-密码于加密
  • Python3.11使用labelimg
  • [Jsprit] Jsprit学习笔记-核心算法VehicleRoutingAlgorithm
  • 代码随想录第十九天 | 110.平衡二叉树,257. 二叉树的所有路径,404.左叶子之和,222. 完全二叉树的节点个数