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

ops/2024/10/21 10:20:42/

在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方法如下:

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

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

java">@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.ppmy.cn/ops/101016.html

相关文章

性能测试笔记

大多数用户期望网站加载时间3秒内 前端常见的性能优化点 1.静态资源增加缓存 2.静态资源使用CDN和独立域名 3.js压缩&#xff0c;并去掉存在的重复请求 4.js位置后移 5.css依赖减少&#xff0c;同时指定&#xff1b; 6.减少Banner图片个数&#xff0c;同时减小大小&…

整流电路和电源滤波方法

1. 简介 什么是整流电路&#xff1f; 整流电路是一种将交流电&#xff08;AC&#xff09;转换为直流电&#xff08;DC&#xff09;的电路&#xff0c;在电源设计、电子设备中广泛应用。本文将深入探讨整流电路的基本原理、常见类型及其在不同领域中的应用。 为什么整流电路重要…

C#面:ASP.NET MVC 中如何用表单认证?

在 ASP.NET MVC 中&#xff0c;可以使用表单认证来验证用户的身份。 表单认证是一种基于 Cookie 的认证方式&#xff0c;它通过在用户登录成功后生成一个包含用户身份信息的加密 Cookie&#xff0c;并将该 Cookie 发送给客户端保存。 当用户发送请求时&#xff0c;服务器会验…

笔记整理—uboot启动过程(7)malloc初始化与内存环境变量

上一章说到了env环境变量并对前两章有关init_sequence部分做了总结&#xff0c;这一章将要对uboot部分的malloc初始化以及内存环境变量进行相关的说明。 mem_malloc_init是用于初始化uboot堆管理器的。自己维护了一段内存&#xff0c;就可用进行malloc和free的操作了。那么这个…

BP神经网络学习内容分享:多层感知机与神经网络

一、多层感知机 多层感知机&#xff08;MLP, Multilayer Perceptron&#xff09;是一种经典的人工神经网络模型&#xff0c;由多个神经元层组成&#xff0c;广泛应用于各种机器学习任务中。以下将介绍MLP的基本原理、结构与训练方法。 1.多层感知机的基本原理 多层感知机&…

QStackedWidget使用整理

需求1做一个主窗口中有一个视频区域&#xff0c;平时放视频&#xff0c;特定条件下显示图片 stackWidget new QStackedWidget((QWidget *)parent_); QWidget *w1,*w2; w1 new QWidget(); w1->setObjectName("video"); …

PowerShell脚本编写:自动化Windows开发工作流程

在现代软件开发中&#xff0c;自动化已经成为提高效率和降低人为错误的重要手段之一。Windows开发者尤其依赖于自动化脚本来简化日常工作流程。PowerShell作为Windows的强大命令行工具和脚本语言&#xff0c;为开发者提供了丰富的功能和灵活性&#xff0c;使得多种开发和管理任…

Tomcat涡轮:企业级WEB动力引擎全解析

目录 一、WEB技术基础 1.1 HTTP协议和B/S结构 1.2 前端三大核心技术 二、WEB框架与资源访问 2.1 WEB资源和访问 2.2 后台应用架构 2.2.1 单体架构 2.2.2 微服务架构 2.2.3 单体架构和微服务比较 三、Tomcat的功能与安装 3.1 Tomcat简介 3.2 安装Tomcat ​编辑 3.…