166 lines
5.6 KiB
Markdown
166 lines
5.6 KiB
Markdown
# 学生信息导入模板下载功能修复记录
|
|
|
|
**日期**: 2025-07-31
|
|
**修改人**: AI Assistant
|
|
**修改原因**: 修复下载导入模板时的"Broken pipe"错误
|
|
|
|
## 问题描述
|
|
|
|
在学生信息管理页面中,点击"下载模板"按钮时出现以下错误:
|
|
|
|
```
|
|
org.springframework.web.context.request.async.AsyncRequestNotUsableException: ServletOutputStream failed to write: Broken pipe
|
|
```
|
|
|
|
### 错误分析
|
|
|
|
1. **文件较大**: 模板文件504KB,传输时间较长
|
|
2. **客户端断开连接**: 用户在下载过程中可能关闭了浏览器或网络中断
|
|
3. **服务器继续写入**: 服务器仍在尝试向已断开的连接写入数据
|
|
4. **异常处理不当**: 后端代码在响应已提交后仍尝试写入错误信息
|
|
|
|
## 解决方案
|
|
|
|
### 1. 后端优化 (XgStudentMsgController.java)
|
|
|
|
#### 主要改进:
|
|
- **文件存在性检查**: 在开始下载前检查模板文件是否存在
|
|
- **连接状态监控**: 在写入过程中检查客户端连接状态
|
|
- **缓冲区优化**: 使用较小的缓冲区(4KB)并定期刷新
|
|
- **异常处理增强**: 专门处理连接断开相关的异常
|
|
- **响应头优化**: 添加缓存控制头
|
|
|
|
#### 关键代码改进:
|
|
```java
|
|
// 检查文件是否存在
|
|
if (!resource.exists()) {
|
|
log.error("模板文件不存在: student_template.xlsx");
|
|
if (!response.isCommitted()) {
|
|
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
|
response.setContentType("text/plain;charset=UTF-8");
|
|
response.getWriter().write("模板文件不存在");
|
|
}
|
|
return;
|
|
}
|
|
|
|
// 连接状态检查
|
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
|
// 检查响应是否已提交(客户端是否断开连接)
|
|
if (response.isCommitted()) {
|
|
log.warn("客户端连接已断开,停止写入数据");
|
|
break;
|
|
}
|
|
|
|
try {
|
|
outputStream.write(buffer, 0, bytesRead);
|
|
totalBytes += bytesRead;
|
|
|
|
// 定期刷新缓冲区,确保数据及时发送
|
|
if (totalBytes % 16384 == 0) { // 每16KB刷新一次
|
|
outputStream.flush();
|
|
}
|
|
} catch (IOException e) {
|
|
// 检查是否是连接断开错误
|
|
if (e.getMessage() != null &&
|
|
(e.getMessage().contains("Broken pipe") ||
|
|
e.getMessage().contains("Connection reset") ||
|
|
e.getMessage().contains("Connection refused"))) {
|
|
log.warn("客户端连接断开,停止下载: {}", e.getMessage());
|
|
break;
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. 前端优化 (index.vue)
|
|
|
|
#### 主要改进:
|
|
- **超时处理**: 添加60秒下载超时机制
|
|
- **错误分类**: 根据不同的错误类型显示相应的错误信息
|
|
- **用户体验**: 优化文件名和提示信息
|
|
- **资源清理**: 确保超时定时器正确清理
|
|
|
|
#### 关键代码改进:
|
|
```javascript
|
|
/** 下载模板操作 */
|
|
const importTemplate = () => {
|
|
// 显示下载进度提示
|
|
const loadingMessage = ElMessage({
|
|
message: '正在下载模板,请稍候...',
|
|
type: 'info',
|
|
duration: 0,
|
|
zIndex: 4000
|
|
});
|
|
|
|
// 设置下载超时时间
|
|
const downloadTimeout = setTimeout(() => {
|
|
ElMessage.closeAll();
|
|
ElMessage.error('下载超时,请稍后重试');
|
|
}, 60000); // 60秒超时
|
|
|
|
proxy
|
|
?.download('studentMsg/studentMsg/importTemplate', {}, `学生信息导入模板_${new Date().getTime()}.xlsx`)
|
|
.then(() => {
|
|
// 下载成功后关闭提示和超时定时器
|
|
clearTimeout(downloadTimeout);
|
|
ElMessage.closeAll();
|
|
ElMessage.success('模板下载成功');
|
|
})
|
|
.catch((error) => {
|
|
// 下载失败时关闭提示和超时定时器
|
|
clearTimeout(downloadTimeout);
|
|
ElMessage.closeAll();
|
|
console.error('下载模板失败:', error);
|
|
|
|
// 根据错误类型显示不同的错误信息
|
|
if (error.message && error.message.includes('timeout')) {
|
|
ElMessage.error('下载超时,请稍后重试');
|
|
} else if (error.message && error.message.includes('403')) {
|
|
ElMessage.error('权限不足,无法下载模板');
|
|
} else if (error.message && error.message.includes('404')) {
|
|
ElMessage.error('模板文件不存在,请联系管理员');
|
|
} else if (error.message && error.message.includes('500')) {
|
|
ElMessage.error('服务器内部错误,请稍后重试');
|
|
} else if (error.message && error.message.includes('Network Error')) {
|
|
ElMessage.error('网络连接异常,请检查网络后重试');
|
|
} else {
|
|
ElMessage.error('下载模板失败,请稍后重试');
|
|
}
|
|
});
|
|
};
|
|
```
|
|
|
|
## 修改文件列表
|
|
|
|
1. **后端文件**:
|
|
- `backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStudentMsgController.java`
|
|
- 优化 `importTemplate()` 方法
|
|
|
|
2. **前端文件**:
|
|
- `web/src/views/xg/xsjcxx/studentMsg/studentMsg/index.vue`
|
|
- 优化 `importTemplate()` 方法
|
|
|
|
## 测试建议
|
|
|
|
1. **正常下载测试**: 验证模板文件能正常下载
|
|
2. **网络中断测试**: 在下载过程中断开网络连接
|
|
3. **浏览器关闭测试**: 在下载过程中关闭浏览器
|
|
4. **大文件传输测试**: 验证大文件的传输稳定性
|
|
5. **并发下载测试**: 多个用户同时下载模板
|
|
|
|
## 预期效果
|
|
|
|
- ✅ 解决"Broken pipe"错误
|
|
- ✅ 提升下载稳定性
|
|
- ✅ 改善用户体验
|
|
- ✅ 增强错误处理能力
|
|
- ✅ 减少服务器资源浪费
|
|
|
|
## 注意事项
|
|
|
|
1. 模板文件大小(504KB)相对较大,建议后续考虑压缩或优化
|
|
2. 定期检查模板文件是否存在和完整性
|
|
3. 监控下载失败率,及时发现问题
|
|
4. 考虑添加下载统计和监控功能 |