diff --git a/dk-common/common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java b/dk-common/common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java index 5ec82f0..311ac1f 100644 --- a/dk-common/common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java +++ b/dk-common/common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java @@ -309,29 +309,6 @@ public class OssClient { } } - public long downloadZip(String key, OutputStream out) { - try { - // 构建下载请求 - DownloadRequest> downloadRequest = DownloadRequest.builder() - // 文件对象 - .getObjectRequest(y -> y.bucket(properties.getBucketName()) - .key(key) - .build()) - .addTransferListener(LoggingTransferListener.create()) - // 使用订阅转换器 - .responseTransformer(AsyncResponseTransformer.toBlockingInputStream()) - .build(); - // 使用 S3TransferManager 下载文件 - Download> responseFuture = transferManager.download(downloadRequest); - // 输出到流中 - try (ResponseInputStream responseStream = responseFuture.completionFuture().join().result()) { // auto-closeable stream - return responseStream.transferTo(out); // 阻塞调用线程 blocks the calling thread - } - } catch (Exception e) { - throw new OssException("文件下载失败,错误信息:[" + e.getMessage() + "]"); - } - } - /** * 删除云存储服务中指定路径下文件 * diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java b/dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java index b20daaf..edb5495 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java @@ -1,9 +1,12 @@ package org.dromara.sample.media.controller; +import cn.hutool.core.util.ObjectUtil; import com.amazonaws.util.IOUtils; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.oss.core.OssClient; import org.dromara.common.oss.factory.OssFactory; import org.dromara.common.satoken.utils.LoginHelper; @@ -11,15 +14,19 @@ import org.dromara.common.sdk.common.HttpResultResponse; import org.dromara.common.sdk.common.PaginationData; import org.dromara.sample.manage.service.IDeviceProService; import org.dromara.sample.media.model.MediaFileDTO; +import org.dromara.sample.media.model.MediaFileEntity; import org.dromara.sample.media.service.IFileService; +import org.dromara.sample.wayline.service.IWaylineJobService; import org.dromara.system.api.model.LoginUser; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import java.io.*; import java.net.URL; import java.net.URLEncoder; import java.util.List; +import java.util.Optional; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -36,6 +43,9 @@ public class FileController { @Autowired private IFileService fileService; + @Autowired + private IWaylineJobService waylineJobService; + /** @@ -87,40 +97,68 @@ public class FileController { @RequestParam(name = "type", required = false) Integer type) { PaginationData filesList = fileService.getMediaFilesPaginationByJobId(workspaceId, page, pageSize,jobId,type); for (MediaFileDTO mediaFileDTO :filesList.getList()){ - mediaFileDTO.setUrl(fileService.getObjectUrl(workspaceId, mediaFileDTO.getFileId()).toString()); + mediaFileDTO.setUrl(fileService.getObjectUrl(mediaFileDTO.getObjectKey()).toString()); } return HttpResultResponse.success(filesList); } @GetMapping("/{workspace_id}/file/downloadZip/{job_id}") - public void downloadZip(HttpServletResponse response, @PathVariable(name = "workspace_id") String workspaceId, - @PathVariable(name = "job_id") String jobId, @RequestParam(name = "jobName", required = false) String jobName) throws UnsupportedEncodingException { - List mediaFileDTO = fileService.getFilesByWorkspaceAndJobId(workspaceId, jobId); - String fileName = "jobName.zip"; + public void downloadZip( HttpServletResponse response, @PathVariable(name = "workspace_id") String workspaceId, + @PathVariable(name = "job_id") String jobId, @RequestParam(name = "jobName", required = false) String jobName) throws IOException { + List mediaFileDTO = fileService.getFilesByWorkspaceAndJobId(workspaceId, jobId).stream().map(MediaFileDTO::getObjectKey).toList(); + if(mediaFileDTO.size() == 0){ + throw new ServiceException("文件不存在"); + } + OssClient storage = OssFactory.instance("mediafile"); response.setContentType("application/zip"); - response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); - try (OutputStream out = response.getOutputStream(); - ZipOutputStream zs = new ZipOutputStream(new BufferedOutputStream(out))) { - - zs.setMethod(ZipOutputStream.DEFLATED); // 设置压缩方法 - - for (MediaFileDTO mediaFile : mediaFileDTO) { - OssClient storage = OssFactory.instance("mediafile"); - //String privateUrlURL = storage.getPrivateUrl(mediaFile.getObjectKey(), 3600); - InputStream is = storage.getObjectContent(mediaFile.getObjectKey()); - String uniqueFileName = mediaFile.getFileName(); // 假设MediaFileDTO有getFileName方法 - ZipEntry entry = new ZipEntry(uniqueFileName); // 使用每个文件的实际名称 - zs.putNextEntry(entry); - IOUtils.copy(is, zs); - zs.closeEntry(); + if(ObjectUtil.isNull(jobName)){ + jobName = waylineJobService.getJobByJobId(workspaceId,jobId).get().getJobName(); + } + String encodedJobName = URLEncoder.encode(jobName, "UTF-8"); + response.setHeader("Content-Disposition", "attachment; filename="+encodedJobName+".zip"); + try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) { + byte[] buffer = new byte[1024]; + for (String objectKey : mediaFileDTO) { + try (InputStream inputStream = storage.getObjectContent(objectKey)) { + // 创建一个新的 ZIP 条目 + zipOut.putNextEntry(new ZipEntry(objectKey)); + + int len; + // 读取文件内容并写入到 ZIP 输出流 + while ((len = inputStream.read(buffer)) != -1) { + zipOut.write(buffer, 0, len); + } + + // 完成当前条目的写入 + zipOut.closeEntry(); + } catch (IOException e) { + e.printStackTrace(); // 如果有某个文件出错,跳过该文件并继续处理其他文件 + } } - } catch (Exception e) { + + zipOut.flush(); + } catch (IOException e) { e.printStackTrace(); } } + @GetMapping("/{workspace_id}/file/download/{file_id}") + public void downloadZip( HttpServletResponse response, @PathVariable(name = "workspace_id") String workspaceId, + @PathVariable(name = "file_id") String fileId) throws IOException { + Optional mediaFileDTO = fileService.getObjectByFileId(workspaceId,fileId); + + OssClient storage = OssFactory.instance("mediafile"); + String jobName = waylineJobService.getJobByJobId(workspaceId,mediaFileDTO.get().getJobId()).get().getJobName(); + String[] filePaths = mediaFileDTO.get().getObjectKey().split("\\."); + FileUtils.setAttachmentResponseHeader(response, jobName+"."+filePaths[filePaths.length-1]); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); + long contentLength = storage.download(mediaFileDTO.get().getObjectKey(), response.getOutputStream()); + response.setContentLengthLong(contentLength); + } + + /** * 根据文件id查询图片的偏航角 * @param fileId diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java b/dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java index 86e0221..f04cfd2 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java @@ -4,9 +4,11 @@ import org.dromara.common.sdk.cloudapi.media.FlightTask; import org.dromara.common.sdk.cloudapi.media.MediaUploadCallbackRequest; import org.dromara.common.sdk.common.PaginationData; import org.dromara.sample.media.model.MediaFileDTO; +import org.dromara.sample.media.model.MediaFileEntity; import java.net.URL; import java.util.List; +import java.util.Optional; /** * @author sean @@ -55,6 +57,10 @@ public interface IFileService { */ URL getObjectUrl(String workspaceId, String fileId); + Optional getObjectByFileId(String workspaceId, String fileId); + + URL getObjectUrl(String objectKey); + /** * Query all media files of a job. * @param workspaceId diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java index 4fcfc1a..f99b84a 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java @@ -140,6 +140,22 @@ public class FileServiceImpl implements IFileService { return storage.getPrivateUrlURL(mediaFileOpt.get().getObjectKey(),3600); } + @Override + public URL getObjectUrl(String objectKey) { + OssClient storage = OssFactory.instance("mediafile"); + return storage.getPrivateUrlURL(objectKey,3600); + } + + + @Override + public Optional getObjectByFileId(String workspaceId, String fileId) { + Optional mediaFileOpt = getMediaByFileId(workspaceId, fileId); + if (mediaFileOpt.isEmpty()) { + throw new IllegalArgumentException("{} 不存在。"); + } + return mediaFileOpt; + } + @Override public List getFilesByWorkspaceAndJobId(String workspaceId, String jobId) { return mapper.selectList(new LambdaQueryWrapper() diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobController.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobController.java index 7edd719..f5c508c 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobController.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobController.java @@ -89,8 +89,9 @@ public class WaylineJobController { @PathVariable(name = "workspace_id") String workspaceId, @RequestParam(name = "proIds" , required = false) List proIds, @RequestParam(name = "fileId" , required = false) String fileId, - @RequestParam(name = "name" , required = false) String name) { - PaginationData data = waylineJobService.getJobsByWorkspaceId(workspaceId, page, pageSize,fileId,proIds,name); + @RequestParam(name = "name" , required = false) String name, + @RequestParam(name = "mediaCount" , required = false) Integer mediaCount) { + PaginationData data = waylineJobService.getJobsByWorkspaceId(workspaceId, page, pageSize,fileId,proIds,name,mediaCount); return HttpResultResponse.success(data); } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/entity/WaylineJobEntity.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/entity/WaylineJobEntity.java index eada478..a99588f 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/entity/WaylineJobEntity.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/entity/WaylineJobEntity.java @@ -97,4 +97,8 @@ public class WaylineJobEntity implements Serializable { @TableField("pro_id") private Integer proId; + + + @TableField("dock_name") + private String dockName; } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobService.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobService.java index 36e4064..38d7037 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobService.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobService.java @@ -28,7 +28,7 @@ public interface IWaylineJobService { * @param endTime The time the job ended. * @return */ - Optional createWaylineJob(CreateJobParam param, String workspaceId, String username, Date beginTime, Date endTime, Integer proId); + Optional createWaylineJob(CreateJobParam param, String workspaceId, String username, Date beginTime, Date endTime, Integer proId,String dockName); /** * Create a sub-task based on the information of the parent task. @@ -71,7 +71,9 @@ public interface IWaylineJobService { * @param pageSize * @return */ - PaginationData getJobsByWorkspaceId(String workspaceId, long page, long pageSize,String fileId,List proIds,String name); + PaginationData getJobsByWorkspaceId(String workspaceId, long page, long pageSize,String fileId,List proIds,String name,Integer mediaCount); + + /** * Query the wayline execution status of the dock. diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/FlightTaskServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/FlightTaskServiceImpl.java index cc9b9d9..b7638b7 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/FlightTaskServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/FlightTaskServiceImpl.java @@ -248,7 +248,7 @@ public class FlightTaskServiceImpl extends AbstractWaylineService implements IFl if(deviceOnline.get().getProId() == null){ throw new SQLException("项目组不存在"); } - Optional waylineJobOpt = waylineJobService.createWaylineJob(param, workspaceId, loginUser.getUsername(), new Date(beginTime), new Date(endTime),deviceOnline.get().getProId()); + Optional waylineJobOpt = waylineJobService.createWaylineJob(param, workspaceId, loginUser.getUsername(), new Date(beginTime), new Date(endTime),deviceOnline.get().getProId(),deviceOnline.get().getNickname()); if (waylineJobOpt.isEmpty()) { throw new SQLException("无法创建路线作业。"); } @@ -286,7 +286,7 @@ public class FlightTaskServiceImpl extends AbstractWaylineService implements IFl if(deviceOnline.get().getProId() == null){ throw new SQLException("项目组不存在"); } - Optional waylineJobOpt = waylineJobService.createWaylineJob(param, workspaceId, username, new Date(beginTime), new Date(endTime),deviceOnline.get().getProId()); + Optional waylineJobOpt = waylineJobService.createWaylineJob(param, workspaceId, username, new Date(beginTime), new Date(endTime),deviceOnline.get().getProId(),deviceOnline.get().getNickname()); if (waylineJobOpt.isEmpty()) { throw new SQLException("无法创建路线作业。"); } @@ -342,6 +342,7 @@ public class FlightTaskServiceImpl extends AbstractWaylineService implements IFl if (waylineFile.isEmpty()) { throw new SQLException("路线文件不存在。"); } + waylineJob.setWaylineName(waylineFile.get().getName()); // get file url URL url = waylineFileService.getObjectUrl(waylineJob.getWorkspaceId(), waylineFile.get().getId()); diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobServiceImpl.java index f3786e7..e69f909 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobServiceImpl.java @@ -92,7 +92,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { } @Override - public Optional createWaylineJob(CreateJobParam param, String workspaceId, String username, Date beginTime, Date endTime,Integer proId) { + public Optional createWaylineJob(CreateJobParam param, String workspaceId, String username, Date beginTime, Date endTime,Integer proId,String dockName) { if (Objects.isNull(param)) { return Optional.empty(); } @@ -116,6 +116,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { .breakPoint(param.getBreakPoint()) .jobType(param.getJobType().getType()) .proId(proId) + .dockSn(dockName) .build(); return insertWaylineJob(jobEntity); @@ -175,7 +176,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { } @Override - public PaginationData getJobsByWorkspaceId(String workspaceId, long page, long pageSize,String fileId,List proIds,String name) { + public PaginationData getJobsByWorkspaceId(String workspaceId, long page, long pageSize,String fileId,List proIds,String name,Integer mediaCount) { LoginUser loginUser = LoginHelper.getLoginUser(); if(ObjectUtil.isAllEmpty(proIds)){ proIds = deviceProService.listDeviceGroup(loginUser.getUserId()); @@ -185,6 +186,9 @@ public class WaylineJobServiceImpl implements IWaylineJobService { if(ObjectUtil.isNotEmpty(fileId)) { waylineJobEntityLambdaQueryWrapper.eq(WaylineJobEntity::getFileId, fileId); } + if(ObjectUtil.isNotEmpty(mediaCount)) { + waylineJobEntityLambdaQueryWrapper.ge(WaylineJobEntity::getMediaCount, mediaCount); + } waylineJobEntityLambdaQueryWrapper.in(ObjectUtil.isAllNotEmpty(proIds),WaylineJobEntity::getProId,proIds); if(ObjectUtil.isNotEmpty(name)){ waylineJobEntityLambdaQueryWrapper.and(wrapper ->{ @@ -297,11 +301,12 @@ public class WaylineJobServiceImpl implements IWaylineJobService { .jobId(entity.getJobId()) .jobName(entity.getName()) .fileId(entity.getFileId()) - .fileName(waylineFileService.getWaylineByWaylineId(entity.getWorkspaceId(), entity.getFileId()) - .orElse(new GetWaylineListResponse()).getName()) + .fileName(entity.getWaylineName()) + // .orElse(new GetWaylineListResponse()).getName()) .dockSn(entity.getDockSn()) - .dockName(deviceService.getDeviceBySn(entity.getDockSn()) - .orElse(DeviceDTO.builder().build()).getNickname()) + .dockName(entity.getDockName()) +// .dockName(deviceService.getDeviceBySn(entity.getDockSn()) +// .orElse(DeviceDTO.builder().build()).getNickname()) .username(entity.getUsername()) .workspaceId(entity.getWorkspaceId()) .status(WaylineJobStatusEnum.IN_PROGRESS.getVal() == entity.getStatus() && @@ -348,17 +353,17 @@ public class WaylineJobServiceImpl implements IWaylineJobService { .uploading(RedisOpsUtils.checkExist(key) && entity.getJobId().equals(((MediaFileCountDTO)RedisOpsUtils.get(key)).getJobId())); return builder.build(); } - - int uploadedSize = fileService.getFilesByWorkspaceAndJobId(entity.getWorkspaceId(), entity.getJobId()).size(); - // All media for this job have been uploaded. - if (uploadedSize >= entity.getMediaCount()) { - return builder.uploadedCount(uploadedSize).build(); - } - RedisOpsUtils.hashSet(countKey, entity.getJobId(), - MediaFileCountDTO.builder() - .jobId(entity.getJobId()) - .mediaCount(entity.getMediaCount()) - .uploadedCount(uploadedSize).build()); +// +// int uploadedSize = fileService.getFilesByWorkspaceAndJobId(entity.getWorkspaceId(), entity.getJobId()).size(); +// //All media for this job have been uploaded. +// if (uploadedSize >= entity.getMediaCount()) { +// return builder.uploadedCount(uploadedSize).build(); +// } +// RedisOpsUtils.hashSet(countKey, entity.getJobId(), +// MediaFileCountDTO.builder() +// .jobId(entity.getJobId()) +// .mediaCount(entity.getMediaCount()) +// .build()); return builder.build(); } } diff --git a/dk-modules/sample/src/main/resources/mapper/WaylineJobMapper.xml b/dk-modules/sample/src/main/resources/mapper/WaylineJobMapper.xml new file mode 100644 index 0000000..a301af7 --- /dev/null +++ b/dk-modules/sample/src/main/resources/mapper/WaylineJobMapper.xml @@ -0,0 +1,23 @@ + + + + + + + +