package org.dromara.safety.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.file.FileUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.oss.core.OssClient;
import org.dromara.common.oss.exception.OssException;
import org.dromara.common.oss.factory.OssFactory;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.project.domain.BusConstructionUser;
import org.dromara.project.domain.BusProjectTeamMember;
import org.dromara.project.service.IBusConstructionUserService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.project.service.IBusProjectTeamMemberService;
import org.dromara.safety.domain.HseQuestionUserAnswer;
import org.dromara.safety.domain.enums.HseSafetyExamTypeEnum;
import org.dromara.safety.domain.dto.questionuseranswer.*;
import org.dromara.safety.domain.vo.questionuseranswer.HseQuestionUserAnswerVo;
import org.dromara.safety.mapper.HseQuestionUserAnswerMapper;
import org.dromara.safety.service.IHseQuestionUserAnswerService;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysOssService;
import org.springframework.beans.BeanUtils;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 用户试卷存储Service业务层处理
 *
 * @author lcj
 * @date 2025-03-24
 */
@Slf4j
@Service
public class HseQuestionUserAnswerServiceImpl extends ServiceImpl<HseQuestionUserAnswerMapper, HseQuestionUserAnswer>
    implements IHseQuestionUserAnswerService {

    @Resource
    private IBusProjectService projectService;

    @Resource
    private ISysOssService ossService;

    @Resource
    private IBusConstructionUserService constructionUserService;

    @Resource
    private IBusProjectTeamMemberService projectTeamMemberService;

    /**
     * 查询用户试卷存储
     *
     * @param id 主键
     * @return 用户试卷存储
     */
    @Override
    public HseQuestionUserAnswerVo queryById(Long id) {
        HseQuestionUserAnswer questionUserAnswer = this.getById(id);
        if (questionUserAnswer == null) {
            throw new ServiceException("用户试卷存储信息不存在", HttpStatus.NOT_FOUND);
        }
        return this.getVo(questionUserAnswer);
    }

    /**
     * 分页查询用户试卷存储列表
     *
     * @param req       查询条件
     * @param pageQuery 分页参数
     * @return 用户试卷存储分页列表
     */
    @Override
    public TableDataInfo<HseQuestionUserAnswerVo> queryPageList(HseQuestionUserAnswerQueryReq req, PageQuery pageQuery) {
        Page<HseQuestionUserAnswer> result = this.page(pageQuery.build(), buildQueryWrapper(req));
        return TableDataInfo.build(this.getVoPage(result));
    }

    /**
     * 查询符合条件的用户试卷存储列表
     *
     * @param req 查询条件
     * @return 用户试卷存储列表
     */
    @Override
    public List<HseQuestionUserAnswerVo> queryList(HseQuestionUserAnswerQueryReq req) {
        LambdaQueryWrapper<HseQuestionUserAnswer> lqw = buildQueryWrapper(req);
        return this.list(lqw).stream().map(this::getVo).toList();
    }

    /**
     * 新增用户试卷存储
     *
     * @param req 用户试卷存储
     * @return 是否新增成功
     */
    @Override
    public Long insertByBo(HseQuestionUserAnswerCreateReq req) {
        // 将实体类和 DTO 进行转换
        HseQuestionUserAnswer questionUserAnswer = new HseQuestionUserAnswer();
        BeanUtils.copyProperties(req, questionUserAnswer);
        List<Long> bankIdList = req.getBankIdList();
        if (CollUtil.isNotEmpty(bankIdList)) {
            String bankIdStr = JSONUtil.toJsonStr(bankIdList);
            questionUserAnswer.setBankId(bankIdStr);
        }
        List<String> answerList = req.getAnswerList();
        if (CollUtil.isNotEmpty(answerList)) {
            String answerStr = JSONUtil.toJsonStr(answerList);
            questionUserAnswer.setAnswer(answerStr);
        }
        // 数据校验
        validEntityBeforeSave(questionUserAnswer, true);
        // 写入数据库
        boolean save = this.save(questionUserAnswer);
        if (!save) {
            throw new ServiceException("新增用户试卷存储失败，数据库异常", HttpStatus.ERROR);
        }
        // 返回新写入的数据
        return questionUserAnswer.getId();
    }

    /**
     * 通过zip文件批量上传用户试卷存储
     *
     * @param multipartFile zip文件
     * @return 是否上传成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchUploadFileByZip(MultipartFile multipartFile, Long projectId) {
        // 1. 校验
        String originalFilename = multipartFile.getOriginalFilename();
        if (originalFilename == null) {
            throw new ServiceException("文件名不存在", HttpStatus.BAD_REQUEST);
        }
        // 校验是否为压缩包zip格式
        String suffix = FileUtil.getSuffix(originalFilename);
        if (!suffix.equals("zip")) {
            throw new ServiceException("请上传zip格式的压缩文件", HttpStatus.BAD_REQUEST);
        }
        // 2. 临时存储文件路径
        // 2.1 压缩包临时文件路径
        File tempZipFile = null;
        String randomStr = RandomUtil.randomString(16);
        String tempZipFilePath = randomStr + "-" + originalFilename;
        // 2.2 解压后的文件夹路径
        File destDir = null;
        String basePath = "unzip_path";
        String destDirPath = String.format("%s/%s/%s/%s", basePath, DateUtils.getDate(), projectId, randomStr);
        // 3. 构建临时存储对象
        List<HseQuestionUserAnswerUploadTemp> tempList = new ArrayList<>();
        try {
            // 4. 创建临时文件
            tempZipFile = File.createTempFile(tempZipFilePath, null);
            multipartFile.transferTo(tempZipFile);
            // 5. 解压 zip
            destDir = new File(destDirPath);
            ZipUtil.unzip(tempZipFile, destDir);
            // 4. 遍历最外层文件夹
            File[] userFolders = destDir.listFiles();
            if (userFolders != null) {
                for (File userFolder : userFolders) {
                    if (userFolder.isDirectory()) {
                        // 5. 获取文件名，格式为 姓名-身份证-满分-得分-及格分，例如 小明-500106200101011234-100-61-60
                        String userFolderName = userFolder.getName();
                        String[] userParts = userFolderName.split("-");
                        // 6. 继续遍历获取每个用户子文件夹里的文件
                        File[] docFolders = userFolder.listFiles();
                        String fileIdStr = null;
                        if (docFolders != null) {
                            // 6.1 遍历文件
                            List<Long> fileIdList = new ArrayList<>();
                            for (File docFolder : docFolders) {
                                if (docFolder.isFile()) {
                                    // 6.2 上传文件
                                    SysOssVo upload = ossService.upload(docFolder);
                                    if (upload != null) {
                                        fileIdList.add(upload.getOssId());
                                    }
                                }
                            }
                            // 6.3 跳过空文件
                            if (fileIdList.isEmpty()) {
                                continue;
                            }
                            fileIdStr = fileIdList.stream()
                                .map(String::valueOf)
                                .collect(Collectors.joining(","));
                        }
                        // 7. 创建临时对象
                        HseQuestionUserAnswerUploadTemp temp = new HseQuestionUserAnswerUploadTemp();
                        temp.setProjectId(projectId);
                        temp.setUserName(userParts[0]);
                        temp.setUserIdCard(userParts[1]);
                        temp.setFullScore(Long.parseLong(userParts[2]));
                        temp.setScore(Long.parseLong(userParts[3]));
                        temp.setPassScore(Long.parseLong(userParts[4]));
                        temp.setFile(fileIdStr);
                        tempList.add(temp);
                    }
                }
            }
        } catch (Exception e) {
            throw new ServiceException("文件上传失败", HttpStatus.ERROR);
        } finally {
            if (tempZipFile != null) {
                // 删除临时文件
                boolean delete = tempZipFile.delete();
                if (!delete) {
                    log.error("临时文件删除失败，路径：{}", tempZipFilePath);
                }
            }
            if (destDir != null) {
                Path dirPath = Paths.get(basePath);
                try {
                    FileUtils.deleteDirectory(dirPath);
                } catch (IOException e) {
                    log.error("解压文件删除失败，路径：{}", destDirPath, e);
                }
            }
        }
        // 8. 遍历临时对象，进行存储
        if (CollUtil.isEmpty(tempList)) {
            return true;
        }
        // 8.1 获取用户身份证列表
        Set<String> idCardList = tempList.stream().map(HseQuestionUserAnswerUploadTemp::getUserIdCard)
            .collect(Collectors.toSet());
        // 8.2 根据用户身份证列表查询用户信息
        Map<String, List<BusConstructionUser>> userIdMap = constructionUserService.lambdaQuery()
            .in(BusConstructionUser::getSfzNumber, idCardList).list()
            .stream().collect(Collectors.groupingBy(BusConstructionUser::getSfzNumber));
        // 8.3 遍历临时对象，构造用户试卷存储对象
        List<HseQuestionUserAnswer> questionUserAnswerList = tempList.stream().map(temp -> {
            HseQuestionUserAnswer questionUserAnswer = new HseQuestionUserAnswer();
            // 8.4 获取对应用户id
            String userIdCard = temp.getUserIdCard();
            Long userId = null;
            if (userIdMap.containsKey(userIdCard)) {
                BusConstructionUser constructionUser = userIdMap.get(userIdCard).get(0);
                userId = constructionUser.getId();
            }
            // 8.5 判断用户是否存在
            if (userId == null) {
                String userName = temp.getUserName();
                String message = String.format("用户[%s：%s]不存在", userName, userIdCard);
                throw new ServiceException(message, HttpStatus.NOT_FOUND);
            }
            questionUserAnswer.setUserId(userId);
            // 8.6 设置其他属性
            questionUserAnswer.setProjectId(temp.getProjectId());
            questionUserAnswer.setScore(temp.getScore());
            String pass = String.format("%s,%s", temp.getPassScore(), temp.getFullScore());
            questionUserAnswer.setPass(pass);
            questionUserAnswer.setFile(temp.getFile());
            questionUserAnswer.setExamType(HseSafetyExamTypeEnum.OFFLINE.getValue());
            return questionUserAnswer;
        }).toList();
        // 9. 保存
        boolean result = this.saveBatch(questionUserAnswerList);
        if (!result) {
            throw new ServiceException("数据库操作失败", HttpStatus.ERROR);
        }
        return true;
    }

    /**
     * 修改用户试卷存储
     *
     * @param req 用户试卷存储
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(HseQuestionUserAnswerUpdateReq req) {
        // 将实体类和 DTO 进行转换
        HseQuestionUserAnswer questionUserAnswer = new HseQuestionUserAnswer();
        BeanUtils.copyProperties(req, questionUserAnswer);
        List<Long> bankIdList = req.getBankIdList();
        if (CollUtil.isNotEmpty(bankIdList)) {
            String bankIdStr = JSONUtil.toJsonStr(bankIdList);
            questionUserAnswer.setBankId(bankIdStr);
        }
        List<String> answerList = req.getAnswerList();
        if (CollUtil.isNotEmpty(answerList)) {
            String answerStr = JSONUtil.toJsonStr(answerList);
            questionUserAnswer.setAnswer(answerStr);
        }
        // 数据校验
        validEntityBeforeSave(questionUserAnswer, false);
        // 判断是否存在
        HseQuestionUserAnswer oldQuestionUserAnswer = this.getById(questionUserAnswer.getId());
        if (oldQuestionUserAnswer == null) {
            throw new ServiceException("修改用户试卷存储失败，数据不存在", HttpStatus.NOT_FOUND);
        }
        // 操作数据库
        return this.updateById(questionUserAnswer);
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(HseQuestionUserAnswer entity, Boolean create) {
        // TODO 做一些数据校验,如唯一约束
        Long projectId = entity.getProjectId();
        if (create) {
            if (projectId == null) {
                throw new ServiceException("项目id不能为空", HttpStatus.BAD_REQUEST);
            }
        }
        if (projectId != null && projectService.getById(projectId) == null) {
            throw new ServiceException("对应项目不存在", HttpStatus.NOT_FOUND);
        }
    }

    /**
     * 校验并批量删除用户试卷存储信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        Long userId = LoginHelper.getUserId();
        List<HseQuestionUserAnswer> questionUserAnswerList = this.listByIds(ids);
        if (isValid) {
            // TODO 做一些业务上的校验,判断是否需要校验
            List<Long> projectId = questionUserAnswerList.stream().map(HseQuestionUserAnswer::getProjectId).toList();
            projectService.validAuth(projectId, userId);
        }
        return this.removeBatchByIds(ids);
    }

    /**
     * 获取用户试卷存储视图对象
     *
     * @param questionUserAnswer 用户试卷存储对象
     * @return 用户试卷存储视图对象
     */
    @Override
    public HseQuestionUserAnswerVo getVo(HseQuestionUserAnswer questionUserAnswer) {
        // 对象转封装类
        HseQuestionUserAnswerVo questionUserAnswerVo = new HseQuestionUserAnswerVo();
        if (questionUserAnswer == null) {
            return questionUserAnswerVo;
        }
        BeanUtils.copyProperties(questionUserAnswer, questionUserAnswerVo);
        // 获取用户试卷题库列表
        String bankId = questionUserAnswer.getBankId();
        if (StringUtils.isNotBlank(bankId)) {
            questionUserAnswerVo.setBankIdList(JSONUtil.toList(bankId, Long.class));
        }
        // 获取用户试卷答案列表
        String answer = questionUserAnswer.getAnswer();
        if (StringUtils.isNotBlank(answer)) {
            questionUserAnswerVo.setAnswerList(JSONUtil.toList(answer, String.class));
        }
        // 获取用户姓名
        Long userId = questionUserAnswer.getUserId();
        if (userId != null) {
            BusConstructionUser constructionUser = constructionUserService.getById(userId);
            questionUserAnswerVo.setUserName(constructionUser.getUserName());
        }
        // 获取用户试卷文件地址
        String file = questionUserAnswer.getFile();
        if (StringUtils.isNotBlank(file)) {
            List<Long> fileIdList = Arrays.stream(file.split(",")).map(Long::parseLong).toList();
            List<String> fileUrlList = ossService.listByIds(fileIdList).stream().map(SysOssVo::getUrl).toList();
            questionUserAnswerVo.setFileUrl(fileUrlList);
        }
        return questionUserAnswerVo;
    }

    /**
     * 获取用户试卷存储查询条件封装
     *
     * @param req 用户试卷存储查询条件
     * @return 用户试卷存储查询条件封装
     */
    @Override
    public LambdaQueryWrapper<HseQuestionUserAnswer> buildQueryWrapper(HseQuestionUserAnswerQueryReq req) {
        LambdaQueryWrapper<HseQuestionUserAnswer> lqw = new LambdaQueryWrapper<>();
        if (req == null) {
            return lqw;
        }
        Long projectId = req.getProjectId();
        String userName = req.getUserName();
        Long teamId = req.getTeamId();
        // 联表查询
        if (StringUtils.isNotBlank(userName)) {
            List<BusConstructionUser> constructionUserList = constructionUserService.lambdaQuery()
                .select(BusConstructionUser::getId)
                .like(BusConstructionUser::getUserName, userName)
                .list();
            if (CollUtil.isNotEmpty(constructionUserList)) {
                List<Long> userIdList = constructionUserList.stream().map(BusConstructionUser::getId).toList();
                lqw.in(HseQuestionUserAnswer::getUserId, userIdList);
            } else {
                lqw.eq(HseQuestionUserAnswer::getUserId, null);
            }
        }
        if (ObjectUtils.isNotEmpty(teamId)) {
            List<BusProjectTeamMember> projectTeamMemberList = projectTeamMemberService.lambdaQuery()
                .select(BusProjectTeamMember::getMemberId)
                .eq(BusProjectTeamMember::getTeamId, teamId)
                .list();
            if (CollUtil.isNotEmpty(projectTeamMemberList)) {
                List<Long> userIdList = projectTeamMemberList.stream().map(BusProjectTeamMember::getMemberId).toList();
                lqw.in(HseQuestionUserAnswer::getUserId, userIdList);
            } else {
                lqw.eq(HseQuestionUserAnswer::getUserId, null);
            }
        }
        // 精准查询
        lqw.eq(ObjectUtils.isNotEmpty(projectId), HseQuestionUserAnswer::getProjectId, projectId);
        return lqw;
    }

    /**
     * 获取用户试卷存储分页对象视图
     *
     * @param questionUserAnswerPage 用户试卷存储分页对象
     * @return 用户试卷存储分页对象视图
     */
    @Override
    public Page<HseQuestionUserAnswerVo> getVoPage(Page<HseQuestionUserAnswer> questionUserAnswerPage) {
        // 获取分页数据
        List<HseQuestionUserAnswer> questionUserAnswerList = questionUserAnswerPage.getRecords();
        // 添加分页信息
        Page<HseQuestionUserAnswerVo> questionUserAnswerVoPage = new Page<>(
            questionUserAnswerPage.getCurrent(),
            questionUserAnswerPage.getSize(),
            questionUserAnswerPage.getTotal()
        );
        if (CollUtil.isEmpty(questionUserAnswerList)) {
            return questionUserAnswerVoPage;
        }
        // 获取用户名
        Set<Long> userIdList = questionUserAnswerList.stream().map(HseQuestionUserAnswer::getUserId).collect(Collectors.toSet());
        List<BusConstructionUser> constructionUserList = constructionUserService.lambdaQuery()
            .select(BusConstructionUser::getId, BusConstructionUser::getUserName)
            .in(BusConstructionUser::getId, userIdList)
            .list();
        Map<Long, String> userNameMap = constructionUserList.stream()
            .collect(Collectors.toMap(BusConstructionUser::getId, BusConstructionUser::getUserName));
        // 获取用户文件
        Set<Long> fileIdList = questionUserAnswerList.stream().map(HseQuestionUserAnswer::getFile).filter(StringUtils::isNotBlank)
            .flatMap(fileId -> Arrays.stream(fileId.split(",")).map(Long::parseLong)).collect(Collectors.toSet());
        Map<Long, List<SysOssVo>> ossMap = ossService.listByIds(fileIdList)
            .stream().collect(Collectors.groupingBy(SysOssVo::getOssId));
        // 对象列表 => 封装对象列表
        List<HseQuestionUserAnswerVo> questionUserAnswerVoList = questionUserAnswerList.stream().map(questionUserAnswer -> {
            HseQuestionUserAnswerVo questionUserAnswerVo = new HseQuestionUserAnswerVo();
            BeanUtils.copyProperties(questionUserAnswer, questionUserAnswerVo);
            // 获取获取用户名
            Long userId = questionUserAnswer.getUserId();
            if (userId != null) {
                questionUserAnswerVo.setUserName(userNameMap.get(userId));
            }
            // 获取用户文件
            String file = questionUserAnswer.getFile();
            if (StringUtils.isNotBlank(file)) {
                List<Long> ossIdList = Arrays.stream(file.split(",")).map(Long::parseLong).toList();
                List<String> fileUrlList = ossIdList.stream().map(ossId -> {
                    String url = "";
                    if (ossMap.containsKey(ossId)) {
                        url = ossMap.get(ossId).get(0).getUrl();
                    }
                    return url;
                }).toList();
                questionUserAnswerVo.setFileUrl(fileUrlList);
            }
            // 获取用户试卷题库列表
            String bankId = questionUserAnswer.getBankId();
            if (StringUtils.isNotBlank(bankId)) {
                questionUserAnswerVo.setBankIdList(JSONUtil.toList(bankId, Long.class));
            }
            // 获取用户试卷答案列表
            String answer = questionUserAnswer.getAnswer();
            if (StringUtils.isNotBlank(answer)) {
                questionUserAnswerVo.setAnswerList(JSONUtil.toList(answer, String.class));
            }
            return questionUserAnswerVo;
        }).toList();
        questionUserAnswerVoPage.setRecords(questionUserAnswerVoList);
        return questionUserAnswerVoPage;
    }

    /**
     * 批量下载用户试卷存储文件
     *
     * @param req      用户试卷存储文件下载请求
     * @param response 设置响应头和向客户端发送文件内容
     */
    @Override
    public void batchDownloadFile(HseQuestionUserAnswerBatchDownloadFileReq req, HttpServletResponse response) {
        // 获取用户试卷存储文件
        List<Long> idList = req.getIdList();
        if (CollUtil.isEmpty(idList)) {
            return;
        }
        List<HseQuestionUserAnswer> questionUserAnswerList = lambdaQuery()
            .in(HseQuestionUserAnswer::getId, idList)
            .list();
        if (CollUtil.isEmpty(questionUserAnswerList)) {
            return;
        }
        // 查询对应施工人员信息
        Set<Long> userIdSet = questionUserAnswerList.stream().map(HseQuestionUserAnswer::getUserId).collect(Collectors.toSet());
        Map<Long, List<BusConstructionUser>> userMap = constructionUserService.lambdaQuery()
            .select(BusConstructionUser::getId, BusConstructionUser::getUserName)
            .in(BusConstructionUser::getId, userIdSet).list()
            .stream().collect(Collectors.groupingBy(BusConstructionUser::getId));
        if (CollUtil.isEmpty(userMap)) {
            return;
        }
        // 设置响应头
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
        try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
            // 遍历所有用户文件
            for (HseQuestionUserAnswer questionUserAnswer : questionUserAnswerList) {
                String file = questionUserAnswer.getFile();
                if (StringUtils.isBlank(file)) {
                    continue;
                }
                Long userId = questionUserAnswer.getUserId();
                BusConstructionUser constructionUser = userMap.get(userId).get(0);
                String userFolder = constructionUser.getUserName() + "-" + constructionUser.getId() + "/";
                // 写入个人文件夹条目
                zos.putNextEntry(new ZipEntry(userFolder));
                zos.closeEntry();
                List<Long> ossIdList = Arrays.stream(file.split(",")).map(Long::parseLong).toList();
                List<SysOssVo> ossVoList = ossService.listByIds(ossIdList);
                // 遍历用户文件
                for (SysOssVo ossVo : ossVoList) {
                    // 获取文件输入流
                    OssClient storage = OssFactory.instance(ossVo.getService());
                    String path = ossVo.getUrl();
                    try (InputStream is = storage.getObjectContent(path)) {
                        // 从路径中提取文件名（可以根据业务规则调整）
                        String fileName = userFolder + "/" + ossVo.getOriginalName();
                        zos.putNextEntry(new ZipEntry(fileName));
                        byte[] buffer = new byte[4096];
                        int len;
                        while ((len = is.read(buffer)) != -1) {
                            zos.write(buffer, 0, len);
                        }
                        zos.closeEntry();
                    } catch (IOException e) {
                        // 针对单个文件处理异常，可以选择记录日志或终止处理
                        throw new OssException("处理文件[" + path + "]失败，错误信息: " + e.getMessage());
                    }
                }
            }
            zos.finish();
        } catch (IOException e) {
            throw new OssException("生成ZIP文件失败，错误信息: " + e.getMessage());
        }
    }

}
