|
|
@@ -1,5 +1,6 @@
|
|
|
package com.dji.sample.media.service.impl;
|
|
|
|
|
|
+import cn.hutool.core.util.ZipUtil;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import com.dji.sample.common.util.CoordinateUtil;
|
|
|
@@ -10,6 +11,7 @@ import com.dji.sample.component.oss.service.impl.OssServiceContext;
|
|
|
import com.dji.sample.manage.model.common.AMap;
|
|
|
import com.dji.sample.manage.model.dto.DeviceDictionaryDTO;
|
|
|
import com.dji.sample.manage.service.IDeviceDictionaryService;
|
|
|
+import com.dji.sample.map.model.param.MediaFileQueryParam;
|
|
|
import com.dji.sample.media.dao.IFileMapper;
|
|
|
import com.dji.sample.media.model.*;
|
|
|
import com.dji.sample.media.service.IFileService;
|
|
|
@@ -21,26 +23,26 @@ import com.dji.sdk.cloudapi.media.MediaUploadCallbackRequest;
|
|
|
import com.dji.sdk.cloudapi.wayline.GetWaylineListResponse;
|
|
|
import com.dji.sdk.common.Pagination;
|
|
|
import com.dji.sdk.common.PaginationData;
|
|
|
-import com.drew.metadata.exif.ExifSubIFDDescriptor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.http.MediaType;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
import java.io.File;
|
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.math.RoundingMode;
|
|
|
import java.net.URL;
|
|
|
+import java.net.URLEncoder;
|
|
|
import java.time.Instant;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.ZoneId;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Optional;
|
|
|
-import java.util.UUID;
|
|
|
+import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -68,6 +70,9 @@ public class FileServiceImpl implements IFileService {
|
|
|
@Autowired
|
|
|
private IWaylineFileService waylineFileService;
|
|
|
|
|
|
+ private static final String IMAGE = "image";
|
|
|
+ private static final String VIDEO = "video";
|
|
|
+
|
|
|
private Optional<MediaFileEntity> getMediaByFingerprint(String workspaceId, String fingerprint) {
|
|
|
MediaFileEntity fileEntity = mapper.selectOne(new LambdaQueryWrapper<MediaFileEntity>()
|
|
|
.eq(MediaFileEntity::getWorkspaceId, workspaceId)
|
|
|
@@ -148,12 +153,29 @@ public class FileServiceImpl implements IFileService {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public PaginationData<MediaFileDTO> getMediaFilesPaginationByWorkspaceId(String workspaceId, long page, long pageSize) {
|
|
|
+ public PaginationData<MediaFileDTO> getMediaFilesPaginationByWorkspaceId(String workspaceId, MediaFileQueryParam param, long page, long pageSize) {
|
|
|
Page<MediaFileEntity> pageData = mapper.selectPage(
|
|
|
new Page<MediaFileEntity>(page, pageSize),
|
|
|
new LambdaQueryWrapper<MediaFileEntity>()
|
|
|
.eq(MediaFileEntity::getWorkspaceId, workspaceId)
|
|
|
- .orderByDesc(MediaFileEntity::getId));
|
|
|
+ .ge(param != null && param.getBeginTime() != null, MediaFileEntity::getCreateTime,param.getBeginTime())
|
|
|
+ .le(param != null && param.getEndTime() != null, MediaFileEntity::getCreateTime,param.getEndTime())
|
|
|
+ .and(StringUtils.hasText(param.getSearchInfo()),
|
|
|
+ wrapper -> wrapper.like( MediaFileEntity::getFileName, param.getSearchInfo())
|
|
|
+ .or().like( MediaFileEntity::getPayload, param.getSearchInfo())
|
|
|
+ ).and(MediaTypeEnum.PIC_ORIGIN.getVal() == param.getMediaType(),
|
|
|
+ wrapper -> wrapper.like( MediaFileEntity::getMediaType, IMAGE)
|
|
|
+ .eq( MediaFileEntity::getIsOriginal, true)
|
|
|
+ ).and(MediaTypeEnum.PIC_SHOT.getVal() == param.getMediaType(),
|
|
|
+ wrapper -> wrapper.like( MediaFileEntity::getMediaType, IMAGE)
|
|
|
+ .eq( MediaFileEntity::getIsOriginal, false)
|
|
|
+ ).and(MediaTypeEnum.VIDEO.getVal() == param.getMediaType(),
|
|
|
+ wrapper -> wrapper.like( MediaFileEntity::getMediaType, VIDEO)
|
|
|
+ ).and(MediaTypeEnum.UNKNOWN.getVal() == param.getMediaType(),
|
|
|
+ wrapper -> wrapper.notLike(MediaFileEntity::getMediaType, VIDEO)
|
|
|
+ .notLike(MediaFileEntity::getMediaType, IMAGE)
|
|
|
+ )
|
|
|
+ .orderByDesc(MediaFileEntity::getCreateTime));
|
|
|
List<MediaFileDTO> records = pageData.getRecords()
|
|
|
.stream()
|
|
|
.map(this::entityConvertToDto)
|
|
|
@@ -186,14 +208,29 @@ public class FileServiceImpl implements IFileService {
|
|
|
Page<MediaFileEntity> pageData = mapper.selectPage(
|
|
|
new Page<MediaFileEntity>(page, pageSize),
|
|
|
new LambdaQueryWrapper<MediaFileEntity>()
|
|
|
- .eq(MediaFileEntity::getWorkspaceId, dirId)
|
|
|
+ .eq(MediaFileEntity::getDirId, dirId)
|
|
|
.orderByDesc(MediaFileEntity::getId));
|
|
|
List<MediaFileDTO> records = pageData.getRecords()
|
|
|
.stream()
|
|
|
.map(this::entityConvertToDto)
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
- return new PaginationData<MediaFileDTO>(records, new Pagination(pageData.getCurrent(), pageData.getSize(), pageData.getTotal()));
|
|
|
+ MediaDirDTO mediaDirDTO = mediaDirService.getMediaDirById(null,String.valueOf(dirId));
|
|
|
+ return new PaginationData<MediaFileDTO>(mediaDirDTO.getDirName(), records, new Pagination(pageData.getCurrent(), pageData.getSize(), pageData.getTotal()));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<MediaFileDTO> getMediaFilesByDirId(String dirId) {
|
|
|
+ List<MediaFileEntity> listData = mapper.selectList(
|
|
|
+ new LambdaQueryWrapper<MediaFileEntity>()
|
|
|
+ .eq(MediaFileEntity::getDirId, dirId)
|
|
|
+ .orderByDesc(MediaFileEntity::getId));
|
|
|
+ List<MediaFileDTO> records = listData
|
|
|
+ .stream()
|
|
|
+ .map(this::entityConvertToDto)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ return records;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -201,7 +238,7 @@ public class FileServiceImpl implements IFileService {
|
|
|
* @param file
|
|
|
* @return
|
|
|
*/
|
|
|
- private MediaFileEntity fileUploadConvertToEntity(String workspaceId, MediaUploadCallbackRequest file) {
|
|
|
+ private synchronized MediaFileEntity fileUploadConvertToEntity(String workspaceId, MediaUploadCallbackRequest file) {
|
|
|
//通过path 获取航线名称,文件夹名称
|
|
|
String waylineName = getWaylineName(file.getPath());
|
|
|
String dirName = getDirName(waylineName, file.getPath());
|
|
|
@@ -229,7 +266,8 @@ public class FileServiceImpl implements IFileService {
|
|
|
//获取图片信息
|
|
|
MediaExifDTO exif = PicExifUtil.getPicExif(file.getObjectKey());
|
|
|
//经纬度转换
|
|
|
- AMap aMap = CoordinateUtil.transform(file.getMetadata().getShootPosition().getLng(),file.getMetadata().getShootPosition().getLat());
|
|
|
+ //AMap aMap = CoordinateUtil.transform(file.getMetadata().getShootPosition().getLng(),file.getMetadata().getShootPosition().getLat());
|
|
|
+ AMap aMap = CoordinateUtil.transform(exif.getLongitude(),exif.getLatitude());
|
|
|
builder.fileName(file.getName())
|
|
|
.filePath(file.getPath())
|
|
|
.fingerprint(file.getFingerprint())
|
|
|
@@ -241,16 +279,23 @@ public class FileServiceImpl implements IFileService {
|
|
|
.tinnyFingerprint(file.getExt().getTinnyFingerprint())
|
|
|
.payload(getDeviceNameByModelKey(file.getExt().getPayloadModelKey()))
|
|
|
.dirId(dirDto.getId())
|
|
|
+ .waylineName(waylineName)
|
|
|
.imageWidth(exif.getImageWidth())
|
|
|
.imageHeight(exif.getImageHeight())
|
|
|
.xResolution(exif.getXResolution())
|
|
|
.yResolution(exif.getYResolution())
|
|
|
- .latitude(new BigDecimal(aMap.getLatitude()).setScale(6, RoundingMode.DOWN))
|
|
|
- .longitude(new BigDecimal(aMap.getLongitude()).setScale(6, RoundingMode.DOWN))
|
|
|
- .absoluteAltitude(new BigDecimal(file.getMetadata().getAbsoluteAltitude()).setScale(6, RoundingMode.DOWN))
|
|
|
- .relativeAltitude(new BigDecimal(file.getMetadata().getRelativeAltitude()).setScale(6, RoundingMode.DOWN))
|
|
|
+ .latitude(BigDecimal.valueOf(aMap.getLatitude()).setScale(6, RoundingMode.DOWN))
|
|
|
+ .longitude( BigDecimal.valueOf(aMap.getLongitude()).setScale(6, RoundingMode.DOWN))
|
|
|
+ .absoluteAltitude(BigDecimal.valueOf(file.getMetadata().getAbsoluteAltitude()).setScale(6, RoundingMode.DOWN))
|
|
|
+ .relativeAltitude(BigDecimal.valueOf(file.getMetadata().getRelativeAltitude()).setScale(6, RoundingMode.DOWN))
|
|
|
.size(ossService.getObjectSize(OssConfiguration.bucket, file.getObjectKey()))
|
|
|
- .pictureTime(file.getMetadata().getCreatedTime() != null ? file.getMetadata().getCreatedTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : null)
|
|
|
+ .pictureTime(file.getMetadata().getCreatedTime() != null ? file.getMetadata().getCreatedTime().atZone(ZoneId.of("UTC+0")).toInstant().toEpochMilli() : null)
|
|
|
+ .longitudeRef(exif.getLongitudeRef())
|
|
|
+ .latitudeRef(exif.getLatitudeRef())
|
|
|
+ .mediaType(exif.getPictureType())
|
|
|
+ .pictureType(exif.getPictureType())
|
|
|
+ .durationSeconds(exif.getDurationSeconds())
|
|
|
+ .taskName(dirDto.getDirName())//先取远程计划任务名称,没有就取文件夹名称
|
|
|
;
|
|
|
}
|
|
|
return builder.build();
|
|
|
@@ -267,7 +312,7 @@ public class FileServiceImpl implements IFileService {
|
|
|
}
|
|
|
|
|
|
private String getWaylineName(String path) {
|
|
|
- if(!StringUtils.isEmpty(path)) {
|
|
|
+ if(StringUtils.hasText(path)) {
|
|
|
String[] pathSplit = path.split("-");
|
|
|
if(pathSplit.length > 1) {
|
|
|
return pathSplit[pathSplit.length - 1];
|
|
|
@@ -278,7 +323,7 @@ public class FileServiceImpl implements IFileService {
|
|
|
|
|
|
//path:DJI_202406241424_027_项目编号0001-新建面状航线2
|
|
|
private String getDirName(String waylineName,String path) {
|
|
|
- if(!StringUtils.isEmpty(path)) {
|
|
|
+ if(StringUtils.hasText(path)) {
|
|
|
String[] pathSplit = path.split("_");
|
|
|
String datetime = pathSplit[1];
|
|
|
return (waylineName + " " + datetime.substring(0,4)+ "-"
|
|
|
@@ -300,6 +345,12 @@ public class FileServiceImpl implements IFileService {
|
|
|
MediaFileDTO.MediaFileDTOBuilder builder = MediaFileDTO.builder();
|
|
|
|
|
|
if (entity != null) {
|
|
|
+ String taskName = entity.getTaskName();
|
|
|
+ if(!StringUtils.hasText(taskName)) {
|
|
|
+ MediaDirDTO mediaDirDTO = mediaDirService.getMediaDirById(null,String.valueOf(entity.getDirId()));
|
|
|
+ taskName = mediaDirDTO.getDirName();
|
|
|
+ }
|
|
|
+ MediaTypeEnum mediaTypeEnum = convertMediaType(entity);
|
|
|
builder.fileName(entity.getFileName())
|
|
|
.fileId(entity.getFileId())
|
|
|
.filePath(entity.getFilePath())
|
|
|
@@ -311,11 +362,180 @@ public class FileServiceImpl implements IFileService {
|
|
|
.createTime(LocalDateTime.ofInstant(
|
|
|
Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()))
|
|
|
.drone(entity.getDrone())
|
|
|
- .jobId(entity.getJobId());
|
|
|
+ .jobId(entity.getJobId())
|
|
|
+ .dirId(entity.getDirId())
|
|
|
+ .waylineName(entity.getWaylineName())
|
|
|
+ .size(entity.getSize())
|
|
|
+ .longitude(entity.getLongitude())
|
|
|
+ .latitude(entity.getLatitude())
|
|
|
+ .imageWidth(entity.getImageWidth())
|
|
|
+ .imageHeight(entity.getImageHeight())
|
|
|
+ .absoluteAltitude(entity.getAbsoluteAltitude())
|
|
|
+ .gimbalYawDegree(entity.getGimbalYawDegree())
|
|
|
+ .relativeAltitude(entity.getRelativeAltitude())
|
|
|
+ .taskName(taskName)
|
|
|
+ .sourceFrom(entity.getSourceFrom())
|
|
|
+ .pictureTime(LocalDateTime.ofInstant(
|
|
|
+ Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()))
|
|
|
+ .xResolution(entity.getXResolution())
|
|
|
+ .yResolution(entity.getYResolution())
|
|
|
+ .url(ossService.getObjectUrl(OssConfiguration.bucket, entity.getObjectKey()).toString())
|
|
|
+ .longitudeRef(entity.getLongitudeRef())
|
|
|
+ .latitudeRef(entity.getLatitudeRef())
|
|
|
+ .mediaType(mediaTypeEnum.getVal())
|
|
|
+ .mediaTypeText(mediaTypeEnum.getText())
|
|
|
+ .pictureType(entity.getPictureType())
|
|
|
+ .durationSeconds(entity.getDurationSeconds());
|
|
|
|
|
|
}
|
|
|
|
|
|
return builder.build();
|
|
|
}
|
|
|
|
|
|
+ private MediaTypeEnum convertMediaType(MediaFileEntity entity) {
|
|
|
+ if(entity.getMediaType().startsWith(IMAGE)) {
|
|
|
+ if(entity.getIsOriginal()) {
|
|
|
+ return MediaTypeEnum.PIC_ORIGIN;
|
|
|
+ } else {
|
|
|
+ return MediaTypeEnum.PIC_SHOT;
|
|
|
+ }
|
|
|
+ } else if(entity.getMediaType().startsWith(VIDEO)) {
|
|
|
+ return MediaTypeEnum.VIDEO;
|
|
|
+ } else if(entity.getMediaType().startsWith("jfif")) {
|
|
|
+ return MediaTypeEnum.PIC_PANORAMA;
|
|
|
+ }
|
|
|
+ return MediaTypeEnum.UNKNOWN;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void deleteFiles(List<String> fileIds) {
|
|
|
+ List<MediaFileEntity> listData = mapper.selectList(
|
|
|
+ new LambdaQueryWrapper<MediaFileEntity>()
|
|
|
+ .in(MediaFileEntity::getFileId, fileIds));
|
|
|
+ for(MediaFileEntity entity : listData) {
|
|
|
+ try {
|
|
|
+ mapper.delete(new LambdaQueryWrapper<MediaFileEntity>().eq(MediaFileEntity::getFileId, entity.getFileId()));
|
|
|
+ ossService.deleteObject(OssConfiguration.bucket, entity.getObjectKey());
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 下载多个文件夹转zip压缩包
|
|
|
+ *
|
|
|
+ * @param workspaceId
|
|
|
+ * @param dirIds
|
|
|
+ * @param response
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void dowloadDirsToZip(String workspaceId, List<String> dirIds, HttpServletResponse response) throws Exception {
|
|
|
+ dowloadToZip(workspaceId,dirIds,response);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 下载多个文件转zip压缩包
|
|
|
+ *
|
|
|
+ * @param workspaceId
|
|
|
+ * @param fileIds
|
|
|
+ * @param response
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void dowloadFilesToZip(String workspaceId, List<String> fileIds, HttpServletResponse response) throws Exception {
|
|
|
+ try {
|
|
|
+ //被压缩文件名称
|
|
|
+ List<String> srcFileNames = new ArrayList<String>();
|
|
|
+ //被压缩文件流集合
|
|
|
+ List<InputStream> srcFiles = new ArrayList<InputStream>();
|
|
|
+
|
|
|
+ List<MediaFileEntity> listData = mapper.selectList(
|
|
|
+ new LambdaQueryWrapper<MediaFileEntity>()
|
|
|
+ .in(MediaFileEntity::getFileId, fileIds)
|
|
|
+ .orderByDesc(MediaFileEntity::getId));
|
|
|
+
|
|
|
+ //如果有附件 进行zip处理
|
|
|
+ String dirName = "";
|
|
|
+ if (listData != null && listData.size() > 0) {
|
|
|
+ MediaDirDTO mediaDirDTO = mediaDirService.getMediaDirById(workspaceId,String.valueOf(listData.get(0).getDirId()));
|
|
|
+ dirName = mediaDirDTO.getDirName();
|
|
|
+ for (MediaFileEntity entity : listData) {
|
|
|
+ //以下代码为获取图片inputStream
|
|
|
+ InputStream ins = ossService.getObject(OssConfiguration.bucket, entity.getObjectKey());
|
|
|
+ if (ins == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //塞入流数组中
|
|
|
+ srcFiles.add(ins);
|
|
|
+ srcFileNames.add(dirName + "/" + entity.getFileName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
|
|
+ response.setCharacterEncoding("UTF-8");
|
|
|
+ response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(dirName + ".zip", "UTF-8"));
|
|
|
+ //多个文件压缩成压缩包返回
|
|
|
+ ZipUtil.zip(response.getOutputStream(), srcFileNames.toArray(new String[srcFileNames.size()]), srcFiles.toArray(new InputStream[srcFiles.size()]));
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 下载多个文件转zip压缩包
|
|
|
+ * @param workspaceId
|
|
|
+ * @param dirIds
|
|
|
+ * @param response
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ private void dowloadToZip(String workspaceId,List<String> dirIds, HttpServletResponse response) throws Exception {
|
|
|
+ try {
|
|
|
+ //被压缩文件名称
|
|
|
+ List<String> srcFileNames = new ArrayList<String>();
|
|
|
+ //被压缩文件流集合
|
|
|
+ List<InputStream> srcFiles = new ArrayList<InputStream>();
|
|
|
+ for(String dirId : dirIds) {
|
|
|
+ if(StringUtils.isEmpty(dirId)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ MediaDirDTO mediaDirDTO = mediaDirService.getMediaDirById(workspaceId, dirId);
|
|
|
+ List<MediaFileEntity> listData = mapper.selectList(
|
|
|
+ new LambdaQueryWrapper<MediaFileEntity>()
|
|
|
+ .eq(MediaFileEntity::getDirId, dirId)
|
|
|
+ .orderByDesc(MediaFileEntity::getId));
|
|
|
+ //如果有附件 进行zip处理
|
|
|
+ if (listData != null && listData.size() > 0) {
|
|
|
+ for (MediaFileEntity entity : listData) {
|
|
|
+ //以下代码为获取图片inputStream
|
|
|
+ InputStream ins = ossService.getObject(OssConfiguration.bucket, entity.getObjectKey());
|
|
|
+ if (ins == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //塞入流数组中
|
|
|
+ srcFiles.add(ins);
|
|
|
+ srcFileNames.add(mediaDirDTO.getDirName() + "/" + entity.getFileName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
|
|
+ response.setCharacterEncoding("UTF-8");
|
|
|
+ response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("下载.zip", "UTF-8"));
|
|
|
+ //多个文件压缩成压缩包返回
|
|
|
+ ZipUtil.zip(response.getOutputStream(), srcFileNames.toArray(new String[srcFileNames.size()]), srcFiles.toArray(new InputStream[srcFiles.size()]));
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<Integer, Long> getParentDirSize(List<Integer> dirIds) {
|
|
|
+ return mapper.selectList( new LambdaQueryWrapper<MediaFileEntity>()
|
|
|
+ .select(MediaFileEntity::getDirId,MediaFileEntity::getSumSize)
|
|
|
+ .in(MediaFileEntity::getDirId, dirIds)
|
|
|
+ .groupBy(MediaFileEntity::getDirId)
|
|
|
+ ).stream()
|
|
|
+ .collect(Collectors.toMap(a -> a.getDirId(), MediaFileEntity::getSumSize));
|
|
|
+ }
|
|
|
+
|
|
|
}
|