package org.sxkj.resource.feign; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.AllArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springblade.core.oss.model.BladeFile; import org.springblade.core.oss.model.OssFile; import org.springblade.core.tenant.annotation.NonDS; import org.springblade.core.tool.utils.FileUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockMultipartFile; import org.springframework.scheduling.annotation.Async; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import org.sxkj.common.utils.HeaderUtils; import org.sxkj.common.utils.ffmpeg.FfmpegConverterUtils; import org.sxkj.resource.builder.OssBuilder; import org.sxkj.resource.entity.Attach; import org.sxkj.resource.model.MinioPojo; import org.sxkj.resource.service.IAttachService; import org.sxkj.resource.vo.AttachTypeStatisticsVO; import org.sxkj.resource.vo.AttachVO; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.*; /** * 附件远程调用服务 * * @author Chill */ @NonDS @RestController @AllArgsConstructor @Slf4j public class AttachClient implements IAttachClient { @Autowired private IAttachService attachService; @Autowired private OssBuilder ossBuilder; @Autowired private MinioPojo pojo; /** * 保存附件表信息 * * @param attach 附件表信息 * @return */ @Override public Boolean saveAttachInfo(Attach attach) { return attachService.saveAttachInfo(attach); } /** * 获取任务下的图片信息 * @param jobs * @return */ public List getAttachData(@RequestParam String jobs) { AttachVO attach = new AttachVO(); attach.setWayLineJobId(jobs); attach.setOrderByCreateTime(true); attach.setAreaCode(HeaderUtils.getAreaCode()); List integers = Arrays.asList("0", "2", "4", "5"); attach.setResultTypes(integers); List resultTypes = attach.getResultTypes(); String wordOrderType = attach.getWordOrderType(); settingResultType(attach, wordOrderType, resultTypes); if (Objects.nonNull(attach.getAiStatus()) && Objects.nonNull(attach.getResultTypes()) && attach.getResultTypes().contains(Attach.RESULT_TYPE_AI)) { attach.setResultTypes(Arrays.asList(Attach.RESULT_TYPE_AI)); } List aiEventMd5s = attachService.findAiEventMd5s(attach.getEventRecordIds()); attach.setMd5s(aiEventMd5s); if (!CollectionUtils.isEmpty(attach.getEventRecordIds())) { attach.setResultTypes(Arrays.asList(Attach.RESULT_TYPE_AI, Attach.RESULT_TYPE_IMG)); } // 使用大分页获取所有数据 Page page = new Page<>(1, 2000); // 或者 Integer.MAX_VALUE List aiAttachImages = attachService.findAiAttachImages(page, attach); return aiAttachImages; } /** * 设置结果类型 * @param attach * @param wordOrderType * @param resultTypes */ private static void settingResultType(AttachVO attach, String wordOrderType, List resultTypes) { if (!StringUtils.isEmpty(wordOrderType) && !CollectionUtils.isEmpty(resultTypes)) { if ("-1".equals(wordOrderType)) { attach.setWordOrderType(null); if (resultTypes.contains(Attach.RESULT_TYPE_IMG)) { resultTypes = Arrays.asList(Attach.RESULT_TYPE_IMG); } } else { if (resultTypes.contains(Attach.RESULT_TYPE_AI)) { resultTypes = Arrays.asList(Attach.RESULT_TYPE_AI); } } attach.setResultTypes(resultTypes); } } @Override public BladeFile saveAttachFile(MultipartFile file, String fileName) throws IOException { BladeFile bladeFile = ossBuilder.template().putFile(pojo.getBucket(),fileName, file.getInputStream()); Long attachId = buildAttach(fileName, file.getSize(), bladeFile, null); bladeFile.setAttachId(attachId); return bladeFile; } @Override public BladeFile saveAttachFile(MultipartFile file, String fileName, String type) throws IOException { BladeFile bladeFile = ossBuilder.template().putFile(pojo.getBucket(),fileName, file.getInputStream()); Long attachId = buildAttach(fileName, file.getSize(), bladeFile, type); bladeFile.setAttachId(attachId); return bladeFile; } /** * 附件上传 * @param file 文件 * @param fileName 文件名称 * @return * @throws IOException */ @Override public BladeFile putFile(MultipartFile file, String fileName) throws IOException { BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream()); return bladeFile; } private Long buildAttach(String fileName, Long fileSize, BladeFile bladeFile, String type) { String fileExtension = FileUtil.getFileExtension(fileName); Attach attach = new Attach(); attach.setDomainUrl(bladeFile.getDomain()); attach.setLink(bladeFile.getLink()); attach.setName(bladeFile.getName()); attach.setOriginalName(bladeFile.getOriginalName()); attach.setAttachSize(fileSize); attach.setExtension(fileExtension); if (null != type) { attach.setResultType(type); } attachService.save(attach); return attach.getId(); } /** * 根据附件ID集合获取去除 cloud-bucket 前缀后的 name 列表 * * @param ids 附件ID集合 * @return 处理后的 name 列表 */ @Override public List getAttachNames(List ids) { return attachService.getAttachNames(ids); } @Override public Map findMetaDataByName(List names) { return attachService.findMetaDataByName(names); } /** * 查询成果数量 * @param jobId 任务id * @return 成果数量 */ @Override public Long findResultNumByJobId(@RequestParam String jobId){ return attachService.findResultNumByJobId(jobId); } /** * 通过md5查询附件信息 * @param md5 * @return */ @Override public Attach getAttachByMd5(@RequestParam String md5) { List list = attachService.list(new LambdaQueryWrapper().eq(Attach::getMd5, md5)); return (list != null && !list.isEmpty()) ? list.get(0) : null; } @Override public Attach getAttachById(String id) { List list = attachService.list(new LambdaQueryWrapper().eq(Attach::getId, id)); return (list != null && !list.isEmpty()) ? list.get(0) : null; } @SneakyThrows @Override @Async public void processingYesterdayVideo(Date startTime, Date endTime) { // 查询昨日视频 List list = attachService.findAttachInfoByYesterday(1, startTime, endTime); log.info("昨日视频数量:" + list.size()); // for (int i = 0; i < list.size(); i++) { log.info("正在处理第" + (i + 1) + "个视频..."); Attach attach = list.get(i); // 获取视频流 OssFile ossFile = ossBuilder.template("minio").statFile(pojo.getBucket(), attach.getName().replace(pojo.getBucket() + "/", "")); String minioPath = pojo.getServerAddress(); String name = addSmallSuffix(attach.getName(), "_show"); String path = ossFile.getName().replace(pojo.getBucket() + "/", ""); String mp4TempPath = minioPath + "/temp/" + UUID.randomUUID().toString().toLowerCase(); // 开始压缩视频 log.info("原始视频地址:" + minioPath + path); File mediaFile = FfmpegConverterUtils.compressVideo(new File(minioPath + path), 5, mp4TempPath); log.info("第" + (i + 1) + "个视频处理完成...{}", mediaFile.getName()); saveAttachFile(new MockMultipartFile( mediaFile.getName(), mediaFile.getName(), "application/octet-stream", new FileInputStream(mediaFile)), name, Attach.RESULT_TYPE_VEDIO_SHOW); log.info("第{}个视频保存入库完成...", (i + 1)); } log.debug("昨日视频处理完成..."); } private static String addSmallSuffix(String fileName, String suffix) { int lastDotIndex = fileName.lastIndexOf("."); if (lastDotIndex != -1) { // 将文件名分成名称和扩展名两部分 String name = fileName.substring(0, lastDotIndex); String extension = fileName.substring(lastDotIndex); // 在名称后面加上_small return name + suffix + extension; } // 如果没有扩展名,直接在末尾加上_small return fileName + suffix; } /** * * @param deviceSn 设备sn * @param timestamp 时间戳 * @param operator 操作人 * @param workspaceId 工作空间id * @return */ @Override public Boolean deleteAttach(String deviceSn, long timestamp, Long operator, String workspaceId) { return attachService.deleteAttach(deviceSn, timestamp, operator, workspaceId); } /** * * @param deviceSn * @param startDate * @param endDate * @param resultTypes * @param areaCode * @return */ @Override public List calculateTheThreeDimensionalArea(String deviceSn, String startDate, String endDate, String resultTypes, String areaCode) { List attachTypeStatisticsVO = attachService.calculateTheThreeDimensionalArea(deviceSn, startDate, endDate, resultTypes, areaCode); return attachTypeStatisticsVO; } }