package com.dji.sample.media.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.dji.sample.common.model.Pagination; import com.dji.sample.common.model.PaginationData; import com.dji.sample.common.model.ResponseResult; import com.dji.sample.component.oss.model.OssConfiguration; import com.dji.sample.component.oss.service.impl.OssServiceContext; import com.dji.sample.manage.model.dto.DeviceDictionaryDTO; import com.dji.sample.manage.model.enums.DeviceDomainEnum; import com.dji.sample.manage.service.IDeviceDictionaryService; import com.dji.sample.media.dao.IFileMapper; import com.dji.sample.media.dao.IMarkMapper; import com.dji.sample.media.dao.INailMapper; import com.dji.sample.media.dao.IZipMapper; import com.dji.sample.media.model.*; import com.dji.sample.media.service.IFileService; import com.dji.sample.media.util.ImgUtil; import com.dji.sample.media.util.MinioFileDownloader; import com.dji.sample.patches.dao.GetPatchesMapper; import com.dji.sample.patches.model.entity.LotInfo; import com.dji.sample.patches.utils.DistrictCodeUtils; import com.dji.sample.patches.utils.TimerUtil; import com.dji.sample.territory.pojo.TerritoryConfigPojo; import com.dji.sample.territory.service.impl.TbFjServiceImpl; import com.dji.sample.territory.utils.ImgZipUtil; import com.dji.sample.territory.utils.WaterMarkUtil; import com.dji.sample.wayline.service.IWaylineFileService; import com.dji.sample.wayline.service.IWaylineJobService; import com.drew.imaging.ImageProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.minio.MinioClient; import io.minio.PutObjectArgs; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.URL; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.*; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import static com.dji.sample.media.util.ImageDownloaderAndCompressor.*; /** * @author sean * @version 0.2 * @date 2021/12/9 */ @Service @Transactional public class FileServiceImpl implements IFileService { @Autowired private IFileMapper mapper; @Autowired private IMarkMapper markMapper; @Autowired private INailMapper nailMapper; @Autowired private IZipMapper zipMapper; @Autowired private GetPatchesMapper patchesMapper; @Autowired private IDeviceDictionaryService deviceDictionaryService; @Autowired private OssServiceContext ossService; @Autowired private TerritoryConfigPojo territoryConfigPojo; @Autowired private IWaylineJobService waylineJobService; @Autowired private IWaylineFileService waylineFileService; @Autowired private MinioPojo pojo; private ObjectMapper objectMapper = new ObjectMapper(); private Optional getMediaByFingerprint(String workspaceId, String fingerprint) { MediaFileEntity fileEntity = mapper.selectOne(new LambdaQueryWrapper() .eq(MediaFileEntity::getWorkspaceId, workspaceId) .eq(MediaFileEntity::getFingerprint, fingerprint)); return Optional.ofNullable(fileEntity); } private Optional getMediaByFileId(String workspaceId, String fileId) { MediaFileEntity fileEntity = mapper.selectOne(new LambdaQueryWrapper() .eq(MediaFileEntity::getWorkspaceId, workspaceId) .eq(MediaFileEntity::getFileId, fileId)); return Optional.ofNullable(fileEntity); } @Override public Boolean checkExist(String workspaceId, String fingerprint) { return this.getMediaByFingerprint(workspaceId, fingerprint).isPresent(); } @Override public Integer saveFile(String workspaceId, FileUploadDTO file) throws ImageProcessingException, IOException { MediaFileEntity fileEntity = this.fileUploadConvertToEntity(file); fileEntity.setWorkspaceId(workspaceId); fileEntity.setIsadd(0); fileEntity.setFileId(UUID.randomUUID().toString()); String url = pojo.getEndpoint() + "/" + pojo.getBucket() + file.getObjectKey(); File downloadedFile = TbFjServiceImpl.downloadFile(url); Object data = ImgUtil.getInfo(downloadedFile); fileEntity.setDroneData(data); return mapper.insert(fileEntity); } public void saveFiles(String workspaceId, FileUploadDTO file) { // 更新文件状态 updateStatue(file.getName()); try { // 下载文件 boolean endsWithMp4 = file.getObjectKey().endsWith(".mp4"); if (endsWithMp4) { // 处理视频文件 // MediaFileZipEntity zipEntity = this.fileUploadConvertToZipEntity(file); // zipEntity.setWorkspaceId(workspaceId); // zipEntity.setFileId(UUID.randomUUID().toString()); // zipMapper.insert(zipEntity); // 处理视频文件的其他逻辑(如果有) } else { // 处理图片文件 String url = pojo.getEndpoint() + "/" + pojo.getBucket() + file.getObjectKey(); File downloadedFile = TbFjServiceImpl.downloadFile(url); File nailFile = new File(ImgZipUtil.compressImage(downloadedFile, 50).toURI()); MediaFileNailEntity nailEntity = this.fileUploadConvertToNailEntity(file); Object data = ImgUtil.getInfo(downloadedFile); nailEntity.setIsadd(0); nailEntity.setIsOriginal(false); nailEntity.setDronedata(data); nailEntity.setWorkspaceId(workspaceId); nailEntity.setFileName("nail" + file.getName()); nailEntity.setObjectKey("/nail" + file.getPath() + "/" + file.getName()); nailEntity.setFilePath("nail" + file.getPath()); String nailName = nailEntity.getObjectKey(); nailEntity.setFileId(UUID.randomUUID().toString()); // 上传图片文件 // uploadFile("http://139.196.74.78:9000", "sxkj", "sxkj2024", "cloud-bucket", file.getObjectKey(), downloadedFile, "image/jpeg"); uploadFile(pojo.getEndpoint(), pojo.getAccessKey(), pojo.getSecretKey(), pojo.getBucket(), nailName, nailFile, "image/jpeg"); // uploadFile("http://139.196.74.78:9000", "sxkj", "sxkj2024", "cloud-bucket", nailName, nailFile, "image/jpeg"); nailMapper.insert(nailEntity); // 处理压缩后的图片文件(如果有) // File zipFile = new File(ImgZipUtil.compressImageAndGetFile(downloadedFile, 0.5f).toURI()); // MediaFileZipEntity zipEntity = this.fileUploadConvertToZipEntity(file); // zipEntity.setIsOriginal(false); // zipEntity.setWorkspaceId(workspaceId); // zipEntity.setFileName("zip" + file.getName()); // zipEntity.setObjectKey("/zip" + file.getPath() + "/" + file.getName()); // zipEntity.setFilePath("zip" + file.getPath()); // String zipName = zipEntity.getObjectKey(); // zipEntity.setFileId(UUID.randomUUID().toString()); // 上传压缩文件 // uploadFile(pojo.getEndpoint(), pojo.getAccessKey(), pojo.getSecretKey(), pojo.getBucket(), zipName, zipFile, "image/jpeg"); // uploadFile("http://139.196.74.78:9000", "sxkj", "sxkj2024", "cloud-bucket", zipName, zipFile, "image/jpeg"); // zipMapper.insert(zipEntity); } } catch (IOException | ImageProcessingException e) { // 处理异常 e.printStackTrace(); } } public void updateStatue(String filename) { if (filename.contains("~")) { String name = TimerUtil.getDkbh(filename); List lotInfos = patchesMapper.selectList(new LambdaQueryWrapper().eq(LotInfo::getDkbh, name)); if (!lotInfos.isEmpty()) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(LotInfo::getDkbh, name) .eq(LotInfo::getInvestigate, 0) .set(LotInfo::getInvestigate, 1); patchesMapper.update(null, updateWrapper); } } } @Override public Object mediaInfo(String filename) { String name = filename; List entitys = mapper.selectList(new LambdaQueryWrapper() .eq(MediaFileEntity::getFileName, name)); if (entitys != null && !entitys.isEmpty()) { for (MediaFileEntity entity : entitys) { if (entity.getDroneData() != null) { return entity.getDroneData(); } } } if (!filename.contains("mark")) { name = "mark" + filename; } List entity = markMapper.selectList(new LambdaQueryWrapper() .eq(MediaFileMarkEntity::getFileName, name)); if (entity != null && !entity.isEmpty()) { for (MediaFileMarkEntity markEntity : entity) { if (markEntity.getDronedata() != null) { return markEntity.getDronedata(); } } } else { String names = "nail" + filename; List entities = nailMapper.selectList(new LambdaQueryWrapper() .eq(MediaFileNailEntity::getFileName, names)); if (entities != null && !entities.isEmpty()) { for (MediaFileNailEntity NailEntity : entities) { if (NailEntity.getDronedata() != null) { return NailEntity.getDronedata(); } } } } return "null"; } @Override public List getAllFilesByWorkspaceId(String workspaceId) { return mapper.selectList(new LambdaQueryWrapper() .eq(MediaFileEntity::getWorkspaceId, workspaceId)) .stream() .map(this::entityConvertToDto) .collect(Collectors.toList()); } @Override public PaginationData mediaQuery(Integer page, Integer pageSize, Long updateStart, Long updateEnd, Long photoStart, Long photoEnd, String jobName, String workspaceId, String type,String jobId) { // 创建查询条件对象 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); // 添加查询条件 queryWrapper.eq(MediaFileEntity::getWorkspaceId, workspaceId); if (updateStart != null && updateEnd != null) { queryWrapper.between(MediaFileEntity::getCreateTime, updateStart, updateEnd); } if (photoStart != null && photoEnd != null) { queryWrapper.apply("JSON_UNQUOTE(JSON_EXTRACT(metadata, '$.createdTime')) BETWEEN {0} AND {1}", photoStart, photoEnd); } if (jobName != null && !jobName.isEmpty()) { List jobIds = waylineJobService.getJobIds(jobName); if (jobIds.isEmpty()) { return new PaginationData<>(Collections.emptyList(), new Pagination(new Page<>(page, pageSize))); } queryWrapper.in(MediaFileEntity::getJobId, jobIds); } if (jobId != null && !jobId.isEmpty()) { queryWrapper.eq(MediaFileEntity::getJobId,jobId); } if (type != null && !type.isEmpty()) { if ("图片".equals(type)) { queryWrapper.likeLeft(MediaFileEntity::getFileName, ".jpeg"); } else if ("视频".equals(type)) { queryWrapper.likeLeft(MediaFileEntity::getFileName, ".mp4"); } } queryWrapper.last("ORDER BY JSON_EXTRACT(metadata, '$.createdTime') DESC"); // 执行查询获取所有结果 List allResults = mapper.selectList(queryWrapper); // 处理结果去重并设置任务名称 Map uniqueFileMap = new LinkedHashMap<>(); List uniqueResults = allResults.stream() .peek(mediaFile -> { String taskNameResult = waylineJobService.getName(mediaFile.getJobId()); mediaFile.setJobName(taskNameResult); }) .filter(mediaFile -> uniqueFileMap.putIfAbsent(mediaFile.getFileName(), mediaFile) == null) .collect(Collectors.toList()); // 计算分页信息 int total = uniqueResults.size(); int start = (page - 1) * pageSize; int end = Math.min(start + pageSize, total); // 获取当前页的结果 List pageResults = uniqueResults.subList(start, end); // 创建临时的 Page 对象 Page resultPage = new Page<>(page, pageSize); resultPage.setRecords(pageResults); resultPage.setTotal(total); // 返回分页数据 return new PaginationData<>(pageResults, new Pagination(resultPage)); } @Override public PaginationData mediaQuerys(Integer page, Integer pageSize, String workspaceId) { // 创建查询条件对象 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); // 添加查询条件 queryWrapper.eq(MediaFileEntity::getWorkspaceId, workspaceId); queryWrapper.last("ORDER BY JSON_EXTRACT(metadata, '$.createdTime') DESC"); // 执行查询获取所有结果 List allResults = mapper.selectList(queryWrapper); // 处理结果去重并设置任务名称 Map uniqueFileMap = new LinkedHashMap<>(); List uniqueResults = allResults.stream() .peek(mediaFile -> { String taskNameResult = waylineJobService.getName(mediaFile.getJobId()); mediaFile.setJobName(taskNameResult); }) .filter(mediaFile -> uniqueFileMap.putIfAbsent(mediaFile.getJobId(), mediaFile) == null) .collect(Collectors.toList()); // 计算分页信息 int total = uniqueResults.size(); int start = (page - 1) * pageSize; int end = Math.min(start + pageSize, total); // 获取当前页的结果 List pageResults = uniqueResults.subList(start, end); // 创建临时的 Page 对象 Page resultPage = new Page<>(page, pageSize); resultPage.setRecords(pageResults); resultPage.setTotal(total); // 返回分页数据 return new PaginationData<>(pageResults, new Pagination(resultPage)); } @Override public PaginationData mediaNailQuery(Integer page, Integer pageSize, Long updateStart, Long updateEnd, Long photoStart, Long photoEnd, String jobName, String workspaceId, String type) { // 创建查询条件对象 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); // 添加查询条件 queryWrapper.eq(MediaFileNailEntity::getWorkspaceId, workspaceId); if (updateStart != null && updateEnd != null) { queryWrapper.between(MediaFileNailEntity::getCreateTime, updateStart, updateEnd); } if (photoStart != null && photoEnd != null) { queryWrapper.apply("JSON_UNQUOTE(JSON_EXTRACT(metadata, '$.createdTime')) BETWEEN {0} AND {1}", photoStart, photoEnd); } if (jobName != null && !jobName.isEmpty()) { List jobIds = waylineJobService.getJobIds(jobName); if (jobIds.isEmpty()) { return new PaginationData<>(Collections.emptyList(), new Pagination(new Page<>(page, pageSize))); } queryWrapper.in(MediaFileNailEntity::getJobId, jobIds); } if (type != null && !type.isEmpty()) { if ("图片".equals(type)) { queryWrapper.likeLeft(MediaFileNailEntity::getFileName, ".jpeg"); } else if ("视频".equals(type)) { queryWrapper.likeLeft(MediaFileNailEntity::getFileName, ".mp4"); } } queryWrapper.last("ORDER BY JSON_EXTRACT(metadata, '$.createdTime') DESC"); // 执行查询获取所有结果 List allResults = nailMapper.selectList(queryWrapper); // 处理结果去重并设置任务名称 Map uniqueFileMap = new LinkedHashMap<>(); List uniqueResults = allResults.stream() .peek(mediaFile -> { String taskNameResult = waylineJobService.getName(mediaFile.getJobId()); mediaFile.setJobName(taskNameResult); }) .filter(mediaFile -> uniqueFileMap.putIfAbsent(mediaFile.getFileName(), mediaFile) == null) .collect(Collectors.toList()); // 计算分页信息 int total = uniqueResults.size(); int start = (page - 1) * pageSize; int end = Math.min(start + pageSize, total); // 获取当前页的结果 List pageResults = uniqueResults.subList(start, end); // 创建临时的 Page 对象 Page resultPage = new Page<>(page, pageSize); resultPage.setRecords(pageResults); resultPage.setTotal(total); // 返回分页数据 return new PaginationData<>(pageResults, new Pagination(resultPage)); } @Override public List listMediaFileEntity(String workspaceId, String jobId) { return mapper.selectList(new LambdaQueryWrapper() .eq(MediaFileEntity::getWorkspaceId, workspaceId).eq(MediaFileEntity::getJobId, jobId)); } public List listByIsadd(String dkbh, String workspaceId) { return mapper.selectList(new LambdaQueryWrapper() .eq(MediaFileEntity::getWorkspaceId, workspaceId) .like(MediaFileEntity::getFileName, dkbh + "~")); } public ResponseResult updateExamByFileId(String fileId) { int examineStatus = getExamByFileId(fileId); if (examineStatus == 1) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(MediaFileEntity::getFileId, fileId) .set(MediaFileEntity::getExamine, 0); mapper.update(null, updateWrapper); return ResponseResult.success("审核未通过"); } else if (examineStatus == 0) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(MediaFileEntity::getFileId, fileId) .set(MediaFileEntity::getExamine, 1); mapper.update(null, updateWrapper); return ResponseResult.success("审核通过"); } return ResponseResult.error("媒体文件不存在"); } public int getExamByFileId(String fileId) { MediaFileEntity entity = mapper.selectOne(new LambdaQueryWrapper() .eq(MediaFileEntity::getFileId, fileId)); return entity.getExamine(); } public String getDkbhName(String name) { int startIndex = name.indexOf("点") + 1; int endIndex = name.indexOf("."); return name.substring(startIndex, endIndex); } @Override public PaginationData getMediaFilesPaginationByWorkspaceId(String workspaceId, long page, long pageSize, MediaFileQueryParam mediaFileQueryParam) { // Page pageData = mapper.selectPage( // new Page(page, pageSize), // new LambdaQueryWrapper() // .eq(MediaFileEntity::getWorkspaceId, workspaceId) // .orderByDesc(MediaFileEntity::getId)); Page pageData = mapper.selectPage(new Page(page, pageSize), new LambdaQueryWrapper() .eq(MediaFileEntity::getWorkspaceId, workspaceId) .orderByDesc(MediaFileEntity::getCreateTime)); List records = pageData.getRecords() .stream() .peek(mediaFile -> { // 获取任务名称并设置到fileId String taskNameResult = waylineJobService.getName(mediaFile.getJobId()); mediaFile.setJobName(taskNameResult); }) .collect(Collectors.toList()); return new PaginationData(records, new Pagination(pageData)); } public int deleteMedia(String workspaceId, String fileId) { int count = mapper.delete(new LambdaUpdateWrapper().eq(MediaFileEntity::getFileId, fileId) .eq(MediaFileEntity::getWorkspaceId, workspaceId)); return count; } @Override public URL getObjectUrl(String workspaceId, String fileId) { Optional mediaFileOpt = getMediaByFileId(workspaceId, fileId); if (mediaFileOpt.isEmpty()) { throw new IllegalArgumentException("{} 不存在"); } return ossService.getObjectUrl(OssConfiguration.bucket, mediaFileOpt.get().getObjectKey()); } @Override public ResponseResult downloadImages(List jobIds) { String localSaveDir = "/home/drone/web/zip"; String downPath="https://wrj.shuixiongit.com/downloadZip/"; String filepath=TimerUtil.getNowDay()+".zip"; try { String bucketPath = "/data/software/minio-data/cloud-bucket"; List prefixes = getUniqueFilePaths(jobIds); MinioFileDownloader downloader = new MinioFileDownloader(bucketPath); downloader.downloadAndZipFolders(prefixes, localSaveDir,filepath); } catch (Exception e) { e.printStackTrace(); return ResponseResult.error("下载失败" + e.getMessage()); } return ResponseResult.success(downPath+filepath); } @Override public List getUniqueFilePaths(List jobIds) { return mapper.selectList( new LambdaQueryWrapper() .in(MediaFileEntity::getJobId, jobIds)) .stream() .map(MediaFileEntity::getFilePath) .distinct() .collect(Collectors.toList()); } @Override public List getFilesByWorkspaceAndJobId(String workspaceId, String jobId) { return mapper.selectList(new LambdaQueryWrapper() .eq(MediaFileEntity::getWorkspaceId, workspaceId) .eq(MediaFileEntity::getJobId, jobId)) .stream() .map(this::entityConvertToDto).collect(Collectors.toList()); } @Override public Boolean updateMediaFile(String workspaceId, MediaFileEntity mediaFileEntity) { /*MediaFileEntity params = new MediaFileEntity(); params.setFileId(mediaFileEntity.getFileId()); params.setWorkspaceId(mediaFileEntity.getWorkspaceId());*/ boolean update1 = new LambdaUpdateChainWrapper<>(mapper).eq(MediaFileEntity::getFileId, mediaFileEntity.getFileId()) .set(MediaFileEntity::getFileName, mediaFileEntity.getFileName()) .set(MediaFileEntity::getCollectStatus, mediaFileEntity.getCollectStatus()) .set(MediaFileEntity::getUserId, mediaFileEntity.getUserId()) .update(); // int update = mapper.update(mediaFileEntity, Wrappers.update(params)); return update1; } /** * Convert the received file object into a database entity object. * * @param file * @return */ private MediaFileEntity fileUploadConvertToEntity(FileUploadDTO file) { MediaFileEntity.MediaFileEntityBuilder builder = MediaFileEntity.builder(); if (file != null) { builder.fileName(file.getName()) .filePath(file.getPath()) .examine(0) .fingerprint(file.getFingerprint()) .objectKey(file.getObjectKey()) .subFileType(file.getSubFileType()) .isOriginal(file.getExt().getIsOriginal()) .jobId(file.getExt().getFlightId()) .drone(file.getExt().getSn()).metadata(file.getMetadata()) .tinnyFingerprint(file.getExt().getTinnyFingerprint()); // domain-type-subType int[] payloadModel = Arrays.stream(file.getExt().getPayloadModelKey().split("-")) .map(Integer::valueOf) .mapToInt(Integer::intValue) .toArray(); Optional payloadDict = deviceDictionaryService .getOneDictionaryInfoByTypeSubType(DeviceDomainEnum.PAYLOAD.getVal(), payloadModel[1], payloadModel[2]); payloadDict.ifPresent(payload -> builder.payload(payload.getDeviceName())); } return builder.build(); } private MediaFileNailEntity fileUploadConvertToNailEntity(FileUploadDTO file) { MediaFileNailEntity.MediaFileNailEntityBuilder builder = MediaFileNailEntity.builder(); if (file != null) { builder.fileName(file.getName()) .fingerprint(file.getFingerprint()) .objectKey(file.getObjectKey()) .subFileType(file.getSubFileType()) .isOriginal(file.getExt().getIsOriginal()) .filePath(file.getPath()) .jobId(file.getExt().getFlightId()) .drone(file.getExt().getSn()).metadata(file.getMetadata()) .tinnyFingerprint(file.getExt().getTinnyFingerprint()); // domain-type-subType int[] payloadModel = Arrays.stream(file.getExt().getPayloadModelKey().split("-")) .map(Integer::valueOf) .mapToInt(Integer::intValue) .toArray(); Optional payloadDict = deviceDictionaryService .getOneDictionaryInfoByTypeSubType(DeviceDomainEnum.PAYLOAD.getVal(), payloadModel[1], payloadModel[2]); payloadDict.ifPresent(payload -> builder.payload(payload.getDeviceName())); } return builder.build(); } private MediaFileZipEntity fileUploadConvertToZipEntity(FileUploadDTO file) { MediaFileZipEntity.MediaFileZipEntityBuilder builder = MediaFileZipEntity.builder(); if (file != null) { builder.fileName(file.getName()) .fingerprint(file.getFingerprint()) .objectKey(file.getObjectKey()) .subFileType(file.getSubFileType()) .isOriginal(file.getExt().getIsOriginal()) .filePath(file.getPath()) .jobId(file.getExt().getFlightId()) .drone(file.getExt().getSn()).metadata(file.getMetadata()) .tinnyFingerprint(file.getExt().getTinnyFingerprint()); // domain-type-subType int[] payloadModel = Arrays.stream(file.getExt().getPayloadModelKey().split("-")) .map(Integer::valueOf) .mapToInt(Integer::intValue) .toArray(); Optional payloadDict = deviceDictionaryService .getOneDictionaryInfoByTypeSubType(DeviceDomainEnum.PAYLOAD.getVal(), payloadModel[1], payloadModel[2]); payloadDict.ifPresent(payload -> builder.payload(payload.getDeviceName())); } return builder.build(); } /** * Convert database entity objects into file data transfer object. * * @param entity * @return */ private MediaFileDTO entityConvertToDto(MediaFileEntity entity) { MediaFileDTO.MediaFileDTOBuilder builder = MediaFileDTO.builder(); if (entity != null) { builder.fileName(entity.getFileName()) .fileId(entity.getFileId()) .filePath(entity.getFilePath()) .isOriginal(entity.getIsOriginal()) .fingerprint(entity.getFingerprint()) .objectKey(entity.getObjectKey()) .tinnyFingerprint(entity.getTinnyFingerprint()) .payload(entity.getPayload()) .metadata(entity.getMetadata()) .createTime(LocalDateTime.ofInstant( Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault())) .drone(entity.getDrone()) .jobId(entity.getJobId()); } return builder.build(); } public static void uploadFile(String endpoint, String accessKey, String secretKey, String bucketName, String objectName, File file, String type) { try { // 创建MinIO客户端实例 MinioClient minioClient = MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); // 上传文件 FileInputStream fileInputStream = new FileInputStream(file); minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .stream(fileInputStream, file.length(), -1) .contentType(type) .build() ); fileInputStream.close(); } catch (Exception e) { throw new RuntimeException("上传文件至服务器失败" + e); } } public static long convertToTimestamp(Date date) { // 获取时间戳(毫秒级别) return date.getTime(); } public List getSameJobId(String jobId) { return mapper.selectList(new LambdaQueryWrapper() .eq(MediaFileEntity::getJobId, jobId)); } public void updateMediaFileNames(String jobId) { // 查询符合条件的数据 List mediaFiles = mapper.selectList(new LambdaQueryWrapper() .eq(MediaFileEntity::getJobId, jobId)); boolean allContainTilde = mediaFiles.stream().allMatch(file -> file.getFileName().contains("~")); boolean noneContainTilde = mediaFiles.stream().noneMatch(file -> file.getFileName().contains("~")); // 如果所有 fileName 都包含 '~' 或者都不包含 '~',将 is_add 字段改为 1 if (allContainTilde || noneContainTilde) { mediaFiles.forEach(file -> { file.setIsadd(1); updateMediaById(file.getId(), file); }); return; } // 筛选出name字段不包含'~'的数据 List filteredFiles = mediaFiles.stream() .filter(file -> !file.getFileName().contains("~")) .collect(Collectors.toList()); for (MediaFileEntity currentFile : filteredFiles) { String currentName = currentFile.getFileName(); Map currentMetadata = JSON.parseObject(JSON.toJSONString(currentFile.getMetadata()), Map.class); Long currentCreatedTime = (Long) currentMetadata.get("createdTime"); // 找到metadata中的createdTime小于当前数据的createdTime且最接近的那条数据 Optional closestFileOpt = mediaFiles.stream() .filter(file -> { Map metadata = JSON.parseObject(JSON.toJSONString(file.getMetadata()), Map.class); Long createdTime = (Long) metadata.get("createdTime"); String filename = file.getFileName(); return createdTime < currentCreatedTime && filename.contains("~"); }) .min((file1, file2) -> { Map metadata1 = JSON.parseObject(JSON.toJSONString(file1.getMetadata()), Map.class); Map metadata2 = JSON.parseObject(JSON.toJSONString(file2.getMetadata()), Map.class); Long time1 = (Long) metadata1.get("createdTime"); Long time2 = (Long) metadata2.get("createdTime"); return Long.compare(currentCreatedTime - time1, currentCreatedTime - time2); }); if (closestFileOpt.isEmpty()) { // 找不到小于的文件,尝试找大于且最接近的文件 closestFileOpt = mediaFiles.stream() .filter(file -> { Map metadata = JSON.parseObject(JSON.toJSONString(file.getMetadata()), Map.class); Long createdTime = (Long) metadata.get("createdTime"); String filename = file.getFileName(); return createdTime > currentCreatedTime && filename.contains("~"); }) .min((file1, file2) -> { Map metadata1 = JSON.parseObject(JSON.toJSONString(file1.getMetadata()), Map.class); Map metadata2 = JSON.parseObject(JSON.toJSONString(file2.getMetadata()), Map.class); Long time1 = (Long) metadata1.get("createdTime"); Long time2 = (Long) metadata2.get("createdTime"); return Long.compare(time1 - currentCreatedTime, time2 - currentCreatedTime); }); } // 提取并替换name字段 closestFileOpt.ifPresent(closestFile -> { String closestName = closestFile.getFileName(); int startIndex = closestName.indexOf("V"); if (startIndex == -1) startIndex = closestName.indexOf("W"); if (startIndex == -1) startIndex = closestName.indexOf("Z"); if (startIndex == -1) startIndex = closestName.indexOf("T"); if (startIndex == -1) { return; } int endIndex = closestName.indexOf(".", startIndex); if (endIndex == -1) { return; } String replacement = closestName.substring(startIndex, endIndex); int currentStartIndex = currentName.indexOf("V"); if (currentStartIndex == -1) currentStartIndex = currentName.indexOf("W"); if (currentStartIndex == -1) currentStartIndex = currentName.indexOf("Z"); if (currentStartIndex == -1) currentStartIndex = currentName.indexOf("T"); if (currentStartIndex == -1) { return; } int currentEndIndex = currentName.indexOf(".", currentStartIndex); if (currentEndIndex == -1) { return; } String newName = currentName.substring(0, currentStartIndex) + replacement + currentName.substring(currentEndIndex); currentFile.setFileName(newName); updateMediaById(currentFile.getId(), currentFile); }); } } public void updateMediaZipFileNames(String jobId) { // 查询符合条件的数据 List mediaFiles = zipMapper.selectList(new LambdaQueryWrapper() .eq(MediaFileZipEntity::getJobId, jobId)); boolean allContainTilde = mediaFiles.stream().allMatch(file -> file.getFileName().contains("~")); boolean noneContainTilde = mediaFiles.stream().noneMatch(file -> file.getFileName().contains("~")); // 如果所有 fileName 都包含 '~' 或者都不包含 '~',将 is_add 字段改为 1 if (allContainTilde || noneContainTilde) { return; } // 筛选出name字段不包含'~'的数据 List filteredFiles = mediaFiles.stream() .filter(file -> !file.getFileName().contains("~")) .collect(Collectors.toList()); for (MediaFileZipEntity currentFile : filteredFiles) { String currentName = currentFile.getFileName(); Map currentMetadata = JSON.parseObject(JSON.toJSONString(currentFile.getMetadata()), Map.class); Long currentCreatedTime = (Long) currentMetadata.get("createdTime"); // 找到metadata中的createdTime小于当前数据的createdTime且最接近的那条数据 Optional closestFileOpt = mediaFiles.stream() .filter(file -> { Map metadata = JSON.parseObject(JSON.toJSONString(file.getMetadata()), Map.class); Long createdTime = (Long) metadata.get("createdTime"); String filename = file.getFileName(); return createdTime < currentCreatedTime && filename.contains("~"); }) .min((file1, file2) -> { Map metadata1 = JSON.parseObject(JSON.toJSONString(file1.getMetadata()), Map.class); Map metadata2 = JSON.parseObject(JSON.toJSONString(file2.getMetadata()), Map.class); Long time1 = (Long) metadata1.get("createdTime"); Long time2 = (Long) metadata2.get("createdTime"); return Long.compare(currentCreatedTime - time1, currentCreatedTime - time2); }); if (closestFileOpt.isEmpty()) { // 找不到小于的文件,尝试找大于且最接近的文件 closestFileOpt = mediaFiles.stream() .filter(file -> { Map metadata = JSON.parseObject(JSON.toJSONString(file.getMetadata()), Map.class); Long createdTime = (Long) metadata.get("createdTime"); String filename = file.getFileName(); return createdTime > currentCreatedTime && filename.contains("~"); }) .min((file1, file2) -> { Map metadata1 = JSON.parseObject(JSON.toJSONString(file1.getMetadata()), Map.class); Map metadata2 = JSON.parseObject(JSON.toJSONString(file2.getMetadata()), Map.class); Long time1 = (Long) metadata1.get("createdTime"); Long time2 = (Long) metadata2.get("createdTime"); return Long.compare(time1 - currentCreatedTime, time2 - currentCreatedTime); }); } // 提取并替换name字段 closestFileOpt.ifPresent(closestFile -> { String closestName = closestFile.getFileName(); int startIndex = closestName.indexOf("V"); if (startIndex == -1) startIndex = closestName.indexOf("W"); if (startIndex == -1) startIndex = closestName.indexOf("Z"); if (startIndex == -1) startIndex = closestName.indexOf("T"); if (startIndex == -1) { return; } int endIndex = closestName.indexOf(".", startIndex); if (endIndex == -1) { return; } String replacement = closestName.substring(startIndex, endIndex); int currentStartIndex = currentName.indexOf("V"); if (currentStartIndex == -1) currentStartIndex = currentName.indexOf("W"); if (currentStartIndex == -1) currentStartIndex = currentName.indexOf("Z"); if (currentStartIndex == -1) currentStartIndex = currentName.indexOf("T"); if (currentStartIndex == -1) { return; } int currentEndIndex = currentName.indexOf(".", currentStartIndex); if (currentEndIndex == -1) { return; } String newName = currentName.substring(0, currentStartIndex) + replacement + currentName.substring(currentEndIndex); currentFile.setFileName(newName); updateZipById(currentFile.getId(), currentFile); }); } } @Override public void updateNailMediaFileNames(String jobId) { try { // 查询符合条件的数据 List mediaFiles = nailMapper.selectList(new LambdaQueryWrapper() .eq(MediaFileNailEntity::getJobId, jobId)); // 判断所有 fileName 是否都包含 '~' 或者都不包含 '~' boolean allContainTilde = mediaFiles.stream().allMatch(file -> file.getFileName().contains("~")); boolean noneContainTilde = mediaFiles.stream().noneMatch(file -> file.getFileName().contains("~")); // 如果所有 fileName 都包含 '~' 或者都不包含 '~',将 is_add 字段改为 1 if (allContainTilde || noneContainTilde) { mediaFiles.forEach(file -> { file.setIsadd(1); updateById(file.getId(), file); }); return; } // 筛选出name字段不包含'~'的数据 List filteredFiles = mediaFiles.stream() .filter(file -> !file.getFileName().contains("~")) .collect(Collectors.toList()); for (MediaFileNailEntity currentFile : filteredFiles) { String currentName = currentFile.getFileName(); Map currentMetadata = JSON.parseObject(JSON.toJSONString(currentFile.getMetadata()), Map.class); Long currentCreatedTime = (Long) currentMetadata.get("createdTime"); // 找到metadata中的createdTime小于当前数据的createdTime且最接近的那条数据 Optional closestFileOpt = mediaFiles.stream() .filter(file -> { Map metadata = JSON.parseObject(JSON.toJSONString(file.getMetadata()), Map.class); Long createdTime = (Long) metadata.get("createdTime"); String filename = file.getFileName(); return createdTime < currentCreatedTime && filename.contains("~"); }) .min((file1, file2) -> { Map metadata1 = JSON.parseObject(JSON.toJSONString(file1.getMetadata()), Map.class); Map metadata2 = JSON.parseObject(JSON.toJSONString(file2.getMetadata()), Map.class); Long time1 = (Long) metadata1.get("createdTime"); Long time2 = (Long) metadata2.get("createdTime"); return Long.compare(currentCreatedTime - time1, currentCreatedTime - time2); }); if (closestFileOpt.isEmpty()) { // 找不到小于的文件,尝试找大于且最接近的文件 closestFileOpt = mediaFiles.stream() .filter(file -> { Map metadata = JSON.parseObject(JSON.toJSONString(file.getMetadata()), Map.class); Long createdTime = (Long) metadata.get("createdTime"); String filename = file.getFileName(); return createdTime > currentCreatedTime && filename.contains("~"); }) .min((file1, file2) -> { Map metadata1 = JSON.parseObject(JSON.toJSONString(file1.getMetadata()), Map.class); Map metadata2 = JSON.parseObject(JSON.toJSONString(file2.getMetadata()), Map.class); Long time1 = (Long) metadata1.get("createdTime"); Long time2 = (Long) metadata2.get("createdTime"); return Long.compare(time1 - currentCreatedTime, time2 - currentCreatedTime); }); } // 提取并替换name字段 closestFileOpt.ifPresent(closestFile -> { String closestName = closestFile.getFileName(); int startIndex = closestName.indexOf("V"); if (startIndex == -1) startIndex = closestName.indexOf("W"); if (startIndex == -1) startIndex = closestName.indexOf("Z"); if (startIndex == -1) startIndex = closestName.indexOf("T"); if (startIndex == -1) { return; } int endIndex = closestName.indexOf(".", startIndex); if (endIndex == -1) { return; } String replacement = closestName.substring(startIndex, endIndex); int currentStartIndex = currentName.indexOf("V"); if (currentStartIndex == -1) currentStartIndex = currentName.indexOf("W"); if (currentStartIndex == -1) currentStartIndex = currentName.indexOf("Z"); if (currentStartIndex == -1) currentStartIndex = currentName.indexOf("T"); if (currentStartIndex == -1) { return; } int currentEndIndex = currentName.indexOf(".", currentStartIndex); if (currentEndIndex == -1) { return; } String newName = currentName.substring(0, currentStartIndex) + replacement + currentName.substring(currentEndIndex); currentFile.setFileName(newName); updateById(currentFile.getId(), currentFile); }); } } catch (Exception e) { e.printStackTrace(); } } public PaginationData getJobId(int pageNum, int pageSize, String workspaceId) { // 分页查询 Page page = new Page<>(pageNum, pageSize); // 使用 QueryWrapper 执行查询 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper .eq("workspace_id", workspaceId) .orderByDesc("create_time"); // 根据 create_time 降序排序 // 执行分页查询 Page resultPage = mapper.selectPage(page, queryWrapper); List result = resultPage.getRecords(); // 根据 job_id 字段进行去重 Map uniqueFilesMap = result.stream() .collect(Collectors.toMap( MediaFileEntity::getJobId, entity -> entity, (existing, replacement) -> existing // 如果有重复的,保留已有的 )); List uniqueFiles = new ArrayList<>(uniqueFilesMap.values()); // 为每个 MediaFileEntity 设置 jobName for (MediaFileEntity mediaFile : uniqueFiles) { String taskNameResult = waylineJobService.getName(mediaFile.getJobId()); mediaFile.setJobName(taskNameResult); } // 使用分页对象构造 Pagination Page newPage = new Page<>(pageNum, pageSize); newPage.setRecords(uniqueFiles); newPage.setTotal(resultPage.getTotal()); // 设置总记录数为原始查询的总记录数 Pagination pagination = new Pagination(newPage); return new PaginationData<>(uniqueFiles, pagination); } @Override public PaginationData getPhotoByJobId(int pageNum, int pageSize, String workspaceId, String jobId) { // 分页查询 Page page = new Page<>(pageNum, pageSize); // 使用 QueryWrapper 来执行查询 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); // 添加查询条件 queryWrapper.eq(MediaFileEntity::getWorkspaceId, workspaceId); queryWrapper.eq(MediaFileEntity::getJobId,jobId); queryWrapper.last("ORDER BY JSON_EXTRACT(metadata, '$.createdTime') DESC"); Page resultPage = mapper.selectPage(page, queryWrapper); List result = resultPage.getRecords(); // 根据 file_name 字段进行去重 Map uniqueFilesMap = result.stream() .collect(Collectors.toMap( MediaFileEntity::getFileName, entity -> entity, (existing, replacement) -> existing // 如果有重复的,保留已有的 )); List uniqueFiles = new ArrayList<>(uniqueFilesMap.values()); // 为每个 MediaFileEntity 设置 jobName for (MediaFileEntity mediaFile : uniqueFiles) { String taskNameResult = waylineJobService.getName(mediaFile.getJobId()); mediaFile.setJobName(taskNameResult); } // 使用分页对象构造 Pagination Page newPage = new Page<>(pageNum, pageSize); newPage.setRecords(uniqueFiles); newPage.setTotal(uniqueFiles.size()); // 设置总记录数为去重后的记录数 Pagination pagination = new Pagination(newPage); return new PaginationData<>(uniqueFiles, pagination); } public List getMedia(String jobId) { return mapper.selectList(new LambdaQueryWrapper() .eq(MediaFileEntity::getJobId, jobId) .groupBy(MediaFileEntity::getFileName)); // 使用groupBy去重 } public void updateById(Integer id, MediaFileNailEntity entity) { // entity.setIsadd(1); UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("id", id); nailMapper.update(entity, updateWrapper); } public void updateZipById(Integer id, MediaFileZipEntity entity) { UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("id", id); zipMapper.update(entity, updateWrapper); } public void updateMediaById(Integer id, MediaFileEntity entity) { entity.setIsadd(1); UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("id", id); mapper.update(entity, updateWrapper); } public void getNoaddFile() { List mediaEntities = mapper.selectList( new LambdaQueryWrapper().eq(MediaFileEntity::getIsadd, 0)); for (MediaFileEntity media : mediaEntities) { // updateNailMediaFileNames(media.getJobId()); updateMediaFileNames(media.getJobId()); // updateMediaZipFileNames(media.getJobId()); } } }