From d9cbc9a24d3ddd3fd94f3d821547c7ecf7bfc974 Mon Sep 17 00:00:00 2001 From: miaowenbo <1670593359@qq.com> Date: Thu, 27 Nov 2025 15:21:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B5=84=E6=BA=90=E5=AD=A6=E4=B9=A0?= =?UTF-8?q?=E6=83=85=E5=86=B5=E5=AF=BC=E5=87=BA-=E4=BD=9C=E4=B8=9A?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E5=AF=BC=E5=87=BA=E6=8E=A5=E5=8F=A3=E8=A1=A5?= =?UTF-8?q?=E5=85=A8=E9=99=84=E4=BB=B6=E5=92=8Czip=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xboe/school/study/api/StudyCourseApi.java | 103 ++++++++++++++++-- 1 file changed, 93 insertions(+), 10 deletions(-) diff --git a/servers/boe-server-all/src/main/java/com/xboe/school/study/api/StudyCourseApi.java b/servers/boe-server-all/src/main/java/com/xboe/school/study/api/StudyCourseApi.java index 855a4c48..ad7f85f3 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/school/study/api/StudyCourseApi.java +++ b/servers/boe-server-all/src/main/java/com/xboe/school/study/api/StudyCourseApi.java @@ -12,6 +12,7 @@ import com.xboe.constants.CacheName; import com.xboe.core.CurrentUser; import com.xboe.core.JsonResponse; import com.xboe.core.api.ApiBaseController; +import com.xboe.core.upload.XFileUploader; import com.xboe.data.outside.IOutSideDataService; import com.xboe.module.course.entity.*; import com.xboe.module.course.service.ICourseContentService; @@ -42,8 +43,7 @@ import javax.annotation.Resource; import javax.persistence.EntityManager; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.OutputStream; +import java.io.*; import java.math.BigDecimal; import java.math.RoundingMode; import java.net.URLEncoder; @@ -52,6 +52,8 @@ import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; /** * 课程学习的内容 @@ -111,6 +113,9 @@ public class StudyCourseApi extends ApiBaseController{ @Resource private IOrganizationService organizationService; + @Resource + private XFileUploader fileUploader; + /** * 用于避免JPA查询后修改entity实体字段,自动更新到数据库 */ @@ -1407,7 +1412,10 @@ public class StudyCourseApi extends ApiBaseController{ } OutputStream outputStream = null; try { - outputStream = response.getOutputStream(); + // 创建临时文件用于存储Excel + File tempExcelFile = File.createTempFile("HomeWorkRecord", ".xlsx"); + String tempExcelPath = tempExcelFile.getAbsolutePath(); + LinkedHashMap exportMap = new LinkedHashMap<>(); // 1.拼接固定表头(课程名称、资源名称、姓名、工号、部门、作业状态、作业成绩、完成时间) exportMap.put("课程名称", "课程名称"); @@ -1418,6 +1426,7 @@ public class StudyCourseApi extends ApiBaseController{ exportMap.put("作业状态", "作业状态"); exportMap.put("作业成绩", "作业成绩"); exportMap.put("完成时间", "完成时间"); + // 2.整理导出数据 // 查询课程名称 StudyCourse studyCourse = new StudyCourse(); studyCourse.setCourseId(courseId); @@ -1439,7 +1448,6 @@ public class StudyCourseApi extends ApiBaseController{ } } } - // 查询特定作业信息 List studyHomeWorks = studyHomeWorkService.getByCourseIdAndContentId(courseId, contentId); // 通过studyHomeWorks中的人员id集合(去重),调用用户中心接口获取人员信息,填充部门字段 @@ -1471,7 +1479,7 @@ public class StudyCourseApi extends ApiBaseController{ } } } - // 将作业信息与用户信息拼接为map + // 3.将作业信息与用户信息拼接为map String finalContentName = contentName; List> dataList = studyHomeWorks.stream().map(hw -> { Map map = new HashMap<>(); @@ -1500,11 +1508,86 @@ public class StudyCourseApi extends ApiBaseController{ map.put("完成时间", hw.getEndTime()); return map; }).collect(Collectors.toList()); - // 设置响应头信息 - response.setContentType("application/octet-stream"); - response.setHeader("Content-disposition", "attachment;filename=HomeWorkRecord.xlsx"); - // 调用动态列excel导出接口 - ExportsExcelSenderUtil.exportDynamic(exportMap, dataList, outputStream, "yyyy-MM-dd HH:mm:ss"); + // 先将Excel数据写入临时文件 + try (FileOutputStream excelOutputStream = new FileOutputStream(tempExcelFile)) { + ExportsExcelSenderUtil.exportDynamic(exportMap, dataList, excelOutputStream, "yyyy-MM-dd HH:mm:ss"); + } + // 4.整理作业的附件信息备用 + // 获取附件信息集合 + Map homeworkFiles = new HashMap<>(); + String savePath = fileUploader.getSavePath(); + for (StudyHomeWork studyHomeWork : studyHomeWorks) { + String filePath = studyHomeWork.getFilePath(); + if (StringUtils.isNotBlank(filePath)) { + String fullPath = savePath + filePath; + log.info("【资源学习情况导出-作业信息】下载附件路径:{}", fullPath); + File file = new File(fullPath); + if (file.exists()) { + // 使用文件名作为zip中的条目名 + String fileName = file.getName(); + // 避免文件名冲突,如果已存在则添加序号 + String zipEntryName = fileName; + int counter = 1; + while (homeworkFiles.containsKey(zipEntryName)) { + int dotIndex = fileName.lastIndexOf('.'); + if (dotIndex > 0) { + zipEntryName = fileName.substring(0, dotIndex) + "_" + counter + fileName.substring(dotIndex); + } else { + zipEntryName = fileName + "_" + counter; + } + counter++; + } + homeworkFiles.put(zipEntryName, fullPath); + } + } + } + // 5.设置响应头信息为zip文件 + response.setContentType("application/zip"); + response.setHeader("Content-disposition", "attachment;filename=HomeWorkRecord.zip"); + outputStream = response.getOutputStream(); + // 6.把输出的附件和导出的excel文件拼接为一个zip导出 + try (ZipOutputStream zos = new ZipOutputStream(outputStream)) { + // 添加Excel文件到zip + byte[] buffer = new byte[1024]; + // 添加Excel文件 + File excelFile = new File(tempExcelPath); + if (excelFile.exists()) { + FileInputStream fis = new FileInputStream(excelFile); + ZipEntry zipEntry = new ZipEntry("HomeWorkRecord.xlsx"); + zos.putNextEntry(zipEntry); + int length; + while ((length = fis.read(buffer)) > 0) { + zos.write(buffer, 0, length); + } + zos.closeEntry(); + fis.close(); + } + // 添加作业附件文件 + // 25.11.27标记:和技术沟通后,按业务此处调用频率不会过高,因此暂不采用多线程下载方案 + // 为了防止命名冲突,附件放在zip的/附件目录下 + // zip规范要求使用 正斜杠/作为路径分隔符,不要用File.separator(在windows上是\,会导致zip解压异常) + String zipFilePath = "附件/"; + for (Map.Entry entry : homeworkFiles.entrySet()) { + String zipEntryName = zipFilePath + entry.getKey(); + String filePath = entry.getValue(); + File file = new File(filePath); + if (file.exists()) { + FileInputStream fis = new FileInputStream(file); + ZipEntry zipEntry = new ZipEntry(zipEntryName); + zos.putNextEntry(zipEntry); + int len; + while ((len = fis.read(buffer)) > 0) { + zos.write(buffer, 0, len); + } + zos.closeEntry(); + fis.close(); + } + } + } + // 删除临时Excel文件 + if (tempExcelFile.exists()) { + tempExcelFile.delete(); + } } catch (Exception e) { log.error("【资源学习情况导出-作业信息】导出资源学习情况错误:{}", e.getMessage()); } finally {