Browse Source

媒体文件处理 1.更新文件信息接口 2.图片,视频 生成缩略图

S0025136190 1 year ago
parent
commit
401b1816e8

+ 15 - 0
Backend/sample/pom.xml

@@ -155,6 +155,21 @@
             <version>5.8.9</version>
             <version>5.8.9</version>
         </dependency>
         </dependency>
 
 
+        <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>0.4.20</version>
+        </dependency>
+
+        <!--视频截取依赖-->
+        <dependency>
+            <groupId>org.bytedeco</groupId>
+            <artifactId>javacv-platform</artifactId>
+            <version>1.5.9</version>
+        </dependency>
+
+
+
     </dependencies>
     </dependencies>
 
 
     <build>
     <build>

+ 9 - 4
Backend/sample/src/main/java/com/dji/sample/common/util/PicExifUtil.java

@@ -37,16 +37,21 @@ import java.text.DecimalFormat;
 @Component
 @Component
 public class PicExifUtil {
 public class PicExifUtil {
 
 
-    private static final String MP4 = ".MP4";
+    public static final String MP4 = ".MP4";
+    public static final String JPG = ".JPG";
 
 
     public static MediaExifDTO getPicExif(String objectKey) {
     public static MediaExifDTO getPicExif(String objectKey) {
+        OssServiceContext ossService = SpringBeanUtilsTest.getBean(OssServiceContext.class);
+        InputStream inputStream = ossService.getObject(OssConfiguration.bucket, objectKey);
+        return getPicExif(inputStream,objectKey.endsWith(MP4));
+    }
+
+    public static MediaExifDTO getPicExif(InputStream inputStream,boolean isVideo) {
         try {
         try {
             MediaExifDTO.MediaExifDTOBuilder builder = MediaExifDTO.builder();
             MediaExifDTO.MediaExifDTOBuilder builder = MediaExifDTO.builder();
-            OssServiceContext ossService = SpringBeanUtilsTest.getBean(OssServiceContext.class);
-            InputStream inputStream = ossService.getObject(OssConfiguration.bucket, objectKey);
             Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
             Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
             //视频
             //视频
-            if(objectKey.endsWith(MP4)) {
+            if(isVideo) {
                 //视频宽高
                 //视频宽高
                 Mp4VideoDirectory mp4VideoDirectory = metadata.getFirstDirectoryOfType(Mp4VideoDirectory.class);
                 Mp4VideoDirectory mp4VideoDirectory = metadata.getFirstDirectoryOfType(Mp4VideoDirectory.class);
                 builder.imageWidth(mp4VideoDirectory.getInteger(Mp4VideoDirectory.TAG_WIDTH));
                 builder.imageWidth(mp4VideoDirectory.getInteger(Mp4VideoDirectory.TAG_WIDTH));

+ 172 - 0
Backend/sample/src/main/java/com/dji/sample/common/util/ThumbnailatorUtil.java

@@ -0,0 +1,172 @@
+package com.dji.sample.common.util;
+
+
+import com.dji.sample.component.oss.model.OssConfiguration;
+import com.dji.sample.component.oss.service.impl.OssServiceContext;
+import com.dji.sample.media.model.MediaExifDTO;
+import com.drew.imaging.ImageMetadataReader;
+import com.drew.metadata.Metadata;
+import com.drew.metadata.exif.ExifIFD0Directory;
+import com.drew.metadata.exif.ExifSubIFDDirectory;
+import com.drew.metadata.exif.GpsDirectory;
+import com.drew.metadata.file.FileTypeDirectory;
+import com.drew.metadata.mp4.Mp4Directory;
+import com.drew.metadata.mp4.media.Mp4VideoDirectory;
+import lombok.extern.slf4j.Slf4j;
+import net.coobird.thumbnailator.Thumbnails;
+import org.bytedeco.javacv.FFmpegFrameGrabber;
+import org.bytedeco.javacv.Frame;
+import org.bytedeco.javacv.Java2DFrameConverter;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author hqjiang
+ * @version 1.0
+ * @date 2024/7/10
+ */
+
+@Slf4j
+@Component
+public class ThumbnailatorUtil {
+
+    private static final String MP4 = ".MP4";
+
+    public static BufferedImage getThumbnail(String objectKey, int width, int height) {
+        try {
+            if(!objectKey.endsWith(MP4)) {
+                OssServiceContext ossService = SpringBeanUtilsTest.getBean(OssServiceContext.class);
+                InputStream inputStream = ossService.getObject(OssConfiguration.bucket, objectKey);
+
+                return Thumbnails.of(inputStream)
+                        .size(width, height)
+                        .outputQuality(0.75f)
+                        .outputFormat("JPEG")
+                        .asBufferedImage();
+            } else {
+                return getVedioImg(objectKey,width,height);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 获取视频图片
+     *
+     * @throws
+     * @Title: gainVedioImg
+     * @param: filePath  文件夹路径
+     * @return: void
+     */
+    public static BufferedImage getVedioImg(String objectKey, int width, int height) {
+        try {
+        OssServiceContext ossService = SpringBeanUtilsTest.getBean(OssServiceContext.class);
+        InputStream inputStream = ossService.getObject(OssConfiguration.bucket, objectKey);
+        BufferedImage bImage =  getImage(inputStream, 20);
+        return Thumbnails.of(bImage)
+                .size(width, height)
+                .outputQuality(0.75f)
+                .outputFormat("JPEG")
+                .asBufferedImage();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+
+    private static BufferedImage getImage(InputStream inputStream, int second) {
+        try {
+            FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputStream);
+            grabber.start();
+            int ftp = grabber.getLengthInFrames();
+            int flag = 0;
+            Frame frame = null;
+            while (flag <= ftp) {
+                //获取帧
+                frame = grabber.grabImage();
+                //过滤前 second 帧,避免出现全黑图片
+                if ((flag > second) && (frame != null)) {
+                    break;
+                }
+                flag++;
+            }
+            String rotate = grabber.getVideoMetadata("rotate");
+            //创建BufferedImage对象
+            Java2DFrameConverter converter = new Java2DFrameConverter();
+            BufferedImage bufferedImage = converter.getBufferedImage(frame);
+            if (rotate != null) {
+                //旋转图片
+                bufferedImage = rotate(bufferedImage, Integer.parseInt(rotate));
+            }
+
+            grabber.close();
+            grabber.stop();
+
+            log.debug("截取视频截图结束:" + System.currentTimeMillis());
+            return bufferedImage;
+        } catch (Exception e) {
+            log.error("获取视频图片失败!", e);
+        }
+        return null;
+    }
+
+    /**
+     * 旋转 根据视频旋转度来调整图片
+     * @param src
+     * @param angel
+     * @return
+     */
+    private static BufferedImage rotate(BufferedImage src, int angel) {
+        int src_width = src.getWidth(null);
+        int src_height = src.getHeight(null);
+        int type = src.getColorModel().getTransparency();
+        Rectangle rect_des = calcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);
+        BufferedImage bufferedImage = new BufferedImage(rect_des.width, rect_des.height, type);
+        Graphics2D graphics2D = bufferedImage.createGraphics();
+        graphics2D.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
+        graphics2D.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
+        graphics2D.drawImage(src, 0, 0, null);
+        graphics2D.dispose();
+        return bufferedImage;
+    }
+
+    /**
+     * 计算图片旋转大小
+     * @param src
+     * @param angel
+     * @return
+     */
+    private static Rectangle calcRotatedSize(Rectangle src, int angel) {
+        if (angel >= 90) {
+            if (angel / 90 % 2 == 1) {
+                int temp = src.height;
+                src.height = src.width;
+                src.width = temp;
+            }
+            angel = angel % 90;
+        }
+        double totalSqrt = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
+        double totalLen = 2 * Math.sin(Math.toRadians(angel) / 2) * totalSqrt;
+        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
+        double angel_dalta_width = Math.atan((double) src.height / src.width);
+        double angel_dalta_height = Math.atan((double) src.width / src.height);
+        int len_width = (int) (totalLen * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
+        int len_height = (int) (totalLen * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
+        int des_width = src.width + len_width * 2;
+        int des_height = src.height + len_height * 2;
+        return new Rectangle(new Dimension(des_width, des_height));
+    }
+}

+ 8 - 0
Backend/sample/src/main/java/com/dji/sample/component/oss/service/IOssService.java

@@ -5,6 +5,7 @@ import com.dji.sdk.cloudapi.storage.OssTypeEnum;
 
 
 import java.io.InputStream;
 import java.io.InputStream;
 import java.net.URL;
 import java.net.URL;
+import java.util.Map;
 
 
 /**
 /**
  * @author sean
  * @author sean
@@ -29,6 +30,9 @@ public interface IOssService {
      */
      */
     URL getObjectUrl(String bucket, String objectKey);
     URL getObjectUrl(String bucket, String objectKey);
 
 
+    URL getObjectUrl(String bucket, String objectKey,Map<String, String> extraQueryParams);
+
+
     /**
     /**
      * Deletes the object in the storage bucket.
      * Deletes the object in the storage bucket.
      * @param bucket
      * @param bucket
@@ -45,8 +49,12 @@ public interface IOssService {
      */
      */
     InputStream getObject(String bucket, String objectKey);
     InputStream getObject(String bucket, String objectKey);
 
 
+    void putObject(String bucket, String objectKey, InputStream input, Map<String, String> userMetadata);
+
     void putObject(String bucket, String objectKey, InputStream input);
     void putObject(String bucket, String objectKey, InputStream input);
 
 
+    boolean objectExists(String bucket, String objectKey);
+
     void createClient();
     void createClient();
 
 
     Long getObjectSize(String bucket, String objectKey);
     Long getObjectSize(String bucket, String objectKey);

+ 16 - 0
Backend/sample/src/main/java/com/dji/sample/component/oss/service/impl/AliyunOssServiceImpl.java

@@ -22,6 +22,7 @@ import org.springframework.stereotype.Service;
 import java.io.InputStream;
 import java.io.InputStream;
 import java.net.URL;
 import java.net.URL;
 import java.util.Date;
 import java.util.Date;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Objects;
 
 
 /**
 /**
@@ -75,6 +76,11 @@ public class AliyunOssServiceImpl implements IOssService {
                 new Date(System.currentTimeMillis() + OssConfiguration.expire * 1000));
                 new Date(System.currentTimeMillis() + OssConfiguration.expire * 1000));
     }
     }
 
 
+    @Override
+    public URL getObjectUrl(String bucket, String objectKey, Map<String, String> extraQueryParams) {
+        return null;
+    }
+
     @Override
     @Override
     public Boolean deleteObject(String bucket, String objectKey) {
     public Boolean deleteObject(String bucket, String objectKey) {
         if (!ossClient.doesObjectExist(bucket, objectKey)) {
         if (!ossClient.doesObjectExist(bucket, objectKey)) {
@@ -89,6 +95,11 @@ public class AliyunOssServiceImpl implements IOssService {
         return ossClient.getObject(bucket, objectKey).getObjectContent();
         return ossClient.getObject(bucket, objectKey).getObjectContent();
     }
     }
 
 
+    @Override
+    public void putObject(String bucket, String objectKey, InputStream input, Map<String, String> userMetadata) {
+
+    }
+
     @Override
     @Override
     public void putObject(String bucket, String objectKey, InputStream input) {
     public void putObject(String bucket, String objectKey, InputStream input) {
         if (ossClient.doesObjectExist(bucket, objectKey)) {
         if (ossClient.doesObjectExist(bucket, objectKey)) {
@@ -98,6 +109,11 @@ public class AliyunOssServiceImpl implements IOssService {
         log.info("Upload FlighttaskCreateFile: {}", objectResult.getETag());
         log.info("Upload FlighttaskCreateFile: {}", objectResult.getETag());
     }
     }
 
 
+    @Override
+    public boolean objectExists(String bucket, String objectKey) {
+        return false;
+    }
+
     public void createClient() {
     public void createClient() {
         if (Objects.nonNull(this.ossClient)) {
         if (Objects.nonNull(this.ossClient)) {
             return;
             return;

+ 16 - 4
Backend/sample/src/main/java/com/dji/sample/component/oss/service/impl/AmazonS3ServiceImpl.java

@@ -22,10 +22,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.PostConstruct;
 import javax.annotation.PostConstruct;
 import java.io.InputStream;
 import java.io.InputStream;
 import java.net.URL;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
 
 
 /**
 /**
  * @author sean
  * @author sean
@@ -66,6 +63,11 @@ public class AmazonS3ServiceImpl implements IOssService {
                 new Date(System.currentTimeMillis() + OssConfiguration.expire * 1000), HttpMethod.GET);
                 new Date(System.currentTimeMillis() + OssConfiguration.expire * 1000), HttpMethod.GET);
     }
     }
 
 
+    @Override
+    public URL getObjectUrl(String bucket, String objectKey, Map<String, String> extraQueryParams) {
+        return null;
+    }
+
     @Override
     @Override
     public Boolean deleteObject(String bucket, String objectKey) {
     public Boolean deleteObject(String bucket, String objectKey) {
         if (!client.doesObjectExist(bucket, objectKey)) {
         if (!client.doesObjectExist(bucket, objectKey)) {
@@ -79,6 +81,11 @@ public class AmazonS3ServiceImpl implements IOssService {
         return client.getObject(bucket, objectKey).getObjectContent().getDelegateStream();
         return client.getObject(bucket, objectKey).getObjectContent().getDelegateStream();
     }
     }
 
 
+    @Override
+    public void putObject(String bucket, String objectKey, InputStream input, Map<String, String> userMetadata) {
+
+    }
+
     @Override
     @Override
     public void putObject(String bucket, String objectKey, InputStream input) {
     public void putObject(String bucket, String objectKey, InputStream input) {
         if (client.doesObjectExist(bucket, objectKey)) {
         if (client.doesObjectExist(bucket, objectKey)) {
@@ -88,6 +95,11 @@ public class AmazonS3ServiceImpl implements IOssService {
         log.info("Upload FlighttaskCreateFile: {}", objectResult.toString());
         log.info("Upload FlighttaskCreateFile: {}", objectResult.toString());
     }
     }
 
 
+    @Override
+    public boolean objectExists(String bucket, String objectKey) {
+        return false;
+    }
+
     public void createClient() {
     public void createClient() {
         if (Objects.nonNull(this.client)) {
         if (Objects.nonNull(this.client)) {
             return;
             return;

+ 45 - 3
Backend/sample/src/main/java/com/dji/sample/component/oss/service/impl/MinIOServiceImpl.java

@@ -18,6 +18,7 @@ import java.io.InputStream;
 import java.net.URL;
 import java.net.URL;
 import java.security.InvalidKeyException;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchAlgorithmException;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Objects;
 
 
 /**
 /**
@@ -30,7 +31,7 @@ import java.util.Objects;
 public class MinIOServiceImpl implements IOssService {
 public class MinIOServiceImpl implements IOssService {
 
 
     private MinioClient client;
     private MinioClient client;
-    
+
     @Override
     @Override
     public OssTypeEnum getOssType() {
     public OssTypeEnum getOssType() {
         return OssTypeEnum.MINIO;
         return OssTypeEnum.MINIO;
@@ -68,6 +69,24 @@ public class MinIOServiceImpl implements IOssService {
             throw new RuntimeException("The file does not exist on the OssConfiguration.");
             throw new RuntimeException("The file does not exist on the OssConfiguration.");
         }
         }
     }
     }
+    public URL getObjectUrl(String bucket, String objectKey,Map<String, String> extraQueryParams) {
+        try {
+            return new URL(
+                    client.getPresignedObjectUrl(
+                            GetPresignedObjectUrlArgs.builder()
+                                    .method(Method.GET)
+                                    .bucket(bucket)
+                                    .object(objectKey)
+                                    .expiry(Math.toIntExact(OssConfiguration.expire))
+                                    .extraQueryParams(extraQueryParams)
+                                    .build()));
+        } catch (ErrorResponseException | InsufficientDataException | InternalException |
+                InvalidKeyException | InvalidResponseException | IOException |
+                NoSuchAlgorithmException | XmlParserException | ServerException e) {
+            throw new RuntimeException("The file does not exist on the OssConfiguration.");
+        }
+    }
+
 
 
     @Override
     @Override
     public Boolean deleteObject(String bucket, String objectKey) {
     public Boolean deleteObject(String bucket, String objectKey) {
@@ -92,16 +111,39 @@ public class MinIOServiceImpl implements IOssService {
         return InputStream.nullInputStream();
         return InputStream.nullInputStream();
     }
     }
 
 
+    @Override
+    public void putObject(String bucket, String objectKey, InputStream input, Map<String, String> userMetadata) {
+        putObjectToMinIO(bucket,objectKey,input,userMetadata);
+    }
+
     @Override
     @Override
     public void putObject(String bucket, String objectKey, InputStream input) {
     public void putObject(String bucket, String objectKey, InputStream input) {
+        putObjectToMinIO(bucket,objectKey,input,null);
+    }
+
+    @Override
+    public boolean objectExists(String bucket, String objectKey) {
+        try {
+            client.statObject(StatObjectArgs.builder().bucket(bucket).object(objectKey).build());
+            return true;
+        } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) {
+            return false;
+        }
+    }
+
+    private void putObjectToMinIO(String bucket, String objectKey, InputStream input, Map<String,String> userMetadata) {
         try {
         try {
             client.statObject(StatObjectArgs.builder().bucket(bucket).object(objectKey).build());
             client.statObject(StatObjectArgs.builder().bucket(bucket).object(objectKey).build());
             throw new RuntimeException("The filename already exists.");
             throw new RuntimeException("The filename already exists.");
         } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) {
         } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) {
             log.info("The file does not exist, start uploading.");
             log.info("The file does not exist, start uploading.");
             try {
             try {
-                ObjectWriteResponse response = client.putObject(
-                        PutObjectArgs.builder().bucket(bucket).object(objectKey).stream(input, input.available(), 0).build());
+                PutObjectArgs.Builder builder = PutObjectArgs.builder();
+                builder.bucket(bucket).object(objectKey).stream(input, input.available(), 0);
+                if(userMetadata != null) {
+                    builder.userMetadata(userMetadata);
+                }
+                ObjectWriteResponse response = client.putObject(builder.build());
                 log.info("Upload FlighttaskCreateFile: {}", response.etag());
                 log.info("Upload FlighttaskCreateFile: {}", response.etag());
             } catch (MinioException | IOException | InvalidKeyException | NoSuchAlgorithmException ex) {
             } catch (MinioException | IOException | InvalidKeyException | NoSuchAlgorithmException ex) {
                 log.error("Failed to upload FlighttaskCreateFile {}.", objectKey);
                 log.error("Failed to upload FlighttaskCreateFile {}.", objectKey);

+ 16 - 0
Backend/sample/src/main/java/com/dji/sample/component/oss/service/impl/OssServiceContext.java

@@ -12,6 +12,7 @@ import java.io.InputStream;
 import java.net.URL;
 import java.net.URL;
 import java.util.Arrays;
 import java.util.Arrays;
 import java.util.List;
 import java.util.List;
+import java.util.Map;
 
 
 /**
 /**
  * @author sean
  * @author sean
@@ -50,6 +51,13 @@ public class OssServiceContext {
         return this.ossService.getObjectUrl(bucket, objectKey);
         return this.ossService.getObjectUrl(bucket, objectKey);
     }
     }
 
 
+    public URL getObjectUrl(String bucket, String objectKey,Map<String, String> extraQueryParams) {
+        if (!StringUtils.hasText(bucket) || !StringUtils.hasText(objectKey)) {
+            throw new IllegalArgumentException();
+        }
+        return this.ossService.getObjectUrl(bucket, objectKey,extraQueryParams);
+    }
+
     public Boolean deleteObject(String bucket, String objectKey) {
     public Boolean deleteObject(String bucket, String objectKey) {
         return this.ossService.deleteObject(bucket, objectKey);
         return this.ossService.deleteObject(bucket, objectKey);
     }
     }
@@ -62,6 +70,10 @@ public class OssServiceContext {
         this.ossService.putObject(bucket, objectKey, stream);
         this.ossService.putObject(bucket, objectKey, stream);
     }
     }
 
 
+    public void putObject(String bucket, String objectKey, InputStream stream, Map<String, String> userMetadata) {
+        this.ossService.putObject(bucket, objectKey, stream,userMetadata);
+    }
+
     void createClient() {
     void createClient() {
         this.ossService.createClient();
         this.ossService.createClient();
     }
     }
@@ -69,4 +81,8 @@ public class OssServiceContext {
     public Long getObjectSize(String bucket, String objectKey) {
     public Long getObjectSize(String bucket, String objectKey) {
         return this.ossService.getObjectSize(bucket,objectKey);
         return this.ossService.getObjectSize(bucket,objectKey);
     }
     }
+
+    public boolean objectExists(String bucket, String objectKey) {
+        return this.ossService.objectExists(bucket,objectKey);
+    }
 }
 }

+ 16 - 0
Backend/sample/src/main/java/com/dji/sample/media/controller/FileController.java

@@ -164,4 +164,20 @@ public class FileController {
         fileService.deleteFiles(ids);
         fileService.deleteFiles(ids);
         return HttpResultResponse.success();
         return HttpResultResponse.success();
     }
     }
+
+    /**
+     * 更新媒体文件信息.
+     * @param mediaFile
+     * @param workspaceId
+     * @param fileId
+     * @return
+     */
+    @PutMapping("/{workspace_id}/updateFile/{file_id}")
+    public HttpResultResponse updateDevice(@RequestBody MediaFileDTO mediaFile,
+                                           @PathVariable("workspace_id") String workspaceId,
+                                           @PathVariable("file_id") String fileId) {
+        mediaFile.setFileId(fileId);
+        boolean isUpd = fileService.updateFile(mediaFile);
+        return isUpd ? HttpResultResponse.success() : HttpResultResponse.error();
+    }
 }
 }

+ 2 - 0
Backend/sample/src/main/java/com/dji/sample/media/model/MediaFileDTO.java

@@ -76,6 +76,8 @@ public class MediaFileDTO {
 
 
     private String url;
     private String url;
 
 
+    private String thumbnailUrl;
+
     private String longitudeRef;
     private String longitudeRef;
 
 
     private String latitudeRef;
     private String latitudeRef;

+ 2 - 0
Backend/sample/src/main/java/com/dji/sample/media/service/IFileService.java

@@ -88,4 +88,6 @@ public interface IFileService {
     void dowloadFilesToZip(String workspaceId, List<String> fileIds, HttpServletResponse response) throws Exception;
     void dowloadFilesToZip(String workspaceId, List<String> fileIds, HttpServletResponse response) throws Exception;
 
 
     Map<Integer,Long> getParentDirSize(List<Integer> dirIds);
     Map<Integer,Long> getParentDirSize(List<Integer> dirIds);
+
+    Boolean updateFile(MediaFileDTO mediaFileDTO);
 }
 }

+ 102 - 5
Backend/sample/src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java

@@ -2,9 +2,11 @@ package com.dji.sample.media.service.impl;
 
 
 import cn.hutool.core.util.ZipUtil;
 import cn.hutool.core.util.ZipUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.dji.sample.common.util.CoordinateUtil;
 import com.dji.sample.common.util.CoordinateUtil;
 import com.dji.sample.common.util.PicExifUtil;
 import com.dji.sample.common.util.PicExifUtil;
+import com.dji.sample.common.util.ThumbnailatorUtil;
 import com.dji.sample.common.util.UserRequest;
 import com.dji.sample.common.util.UserRequest;
 import com.dji.sample.component.oss.model.OssConfiguration;
 import com.dji.sample.component.oss.model.OssConfiguration;
 import com.dji.sample.component.oss.service.impl.OssServiceContext;
 import com.dji.sample.component.oss.service.impl.OssServiceContext;
@@ -32,10 +34,10 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.MultipartFile;
 
 
+import javax.imageio.ImageIO;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponse;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
+import java.awt.image.BufferedImage;
+import java.io.*;
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.math.RoundingMode;
 import java.net.URL;
 import java.net.URL;
@@ -76,6 +78,11 @@ public class FileServiceImpl implements IFileService {
 
 
     private static final String IMAGE = "image";
     private static final String IMAGE = "image";
     private static final String VIDEO = "video";
     private static final String VIDEO = "video";
+    private static final String TAIL = "_100x100";
+    private static final String T_PATH = "thumbnails/";
+    private static final String DOT = ".";
+    private static final String SPLIT_DOT = "\\.";
+    private static final String JPEG = "JPEG";
 
 
     private Optional<MediaFileEntity> getMediaByFingerprint(String workspaceId, String fingerprint) {
     private Optional<MediaFileEntity> getMediaByFingerprint(String workspaceId, String fingerprint) {
         MediaFileEntity fileEntity = mapper.selectOne(new LambdaQueryWrapper<MediaFileEntity>()
         MediaFileEntity fileEntity = mapper.selectOne(new LambdaQueryWrapper<MediaFileEntity>()
@@ -144,7 +151,8 @@ public class FileServiceImpl implements IFileService {
         MediaFileEntity fileEntity = this.fileUploadConvertToEntity(workspaceId,file);
         MediaFileEntity fileEntity = this.fileUploadConvertToEntity(workspaceId,file);
         fileEntity.setWorkspaceId(workspaceId);
         fileEntity.setWorkspaceId(workspaceId);
         fileEntity.setFileId(UUID.randomUUID().toString());
         fileEntity.setFileId(UUID.randomUUID().toString());
-        return mapper.insert(fileEntity);
+        int result = mapper.insert(fileEntity);
+        return result;
     }
     }
 
 
     @Override
     @Override
@@ -263,12 +271,16 @@ public class FileServiceImpl implements IFileService {
             }
             }
             dirDto = mediaDirService.createDir(dirBuilder.build());
             dirDto = mediaDirService.createDir(dirBuilder.build());
         }
         }
+        //生成缩略图
+        String tObjectKey = getThumbnailObjectKey(file.getName());
+        putThumbnailImage(tObjectKey,file.getObjectKey());
 
 
         MediaFileEntity.MediaFileEntityBuilder builder = MediaFileEntity.builder();
         MediaFileEntity.MediaFileEntityBuilder builder = MediaFileEntity.builder();
 
 
         if (file != null) {
         if (file != null) {
             //获取图片信息
             //获取图片信息
             MediaExifDTO exif = PicExifUtil.getPicExif(file.getObjectKey());
             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());
             AMap aMap = CoordinateUtil.transform(exif.getLongitude(),exif.getLatitude());
@@ -355,6 +367,8 @@ public class FileServiceImpl implements IFileService {
                 taskName = mediaDirDTO.getDirName();
                 taskName = mediaDirDTO.getDirName();
             }
             }
             MediaTypeEnum mediaTypeEnum = convertMediaType(entity);
             MediaTypeEnum mediaTypeEnum = convertMediaType(entity);
+            String url = ossService.getObjectUrl(OssConfiguration.bucket, entity.getObjectKey()).toString();
+            String thumbnailURL = getThumbnailURL(entity);
             builder.fileName(entity.getFileName())
             builder.fileName(entity.getFileName())
                     .fileId(entity.getFileId())
                     .fileId(entity.getFileId())
                     .filePath(entity.getFilePath())
                     .filePath(entity.getFilePath())
@@ -383,7 +397,8 @@ public class FileServiceImpl implements IFileService {
                             Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()))
                             Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()))
                     .xResolution(entity.getXResolution())
                     .xResolution(entity.getXResolution())
                     .yResolution(entity.getYResolution())
                     .yResolution(entity.getYResolution())
-                    .url(ossService.getObjectUrl(OssConfiguration.bucket, entity.getObjectKey()).toString())
+                    .url(url)
+                    .thumbnailUrl(null == thumbnailURL ? url : thumbnailURL)
                     .longitudeRef(entity.getLongitudeRef())
                     .longitudeRef(entity.getLongitudeRef())
                     .latitudeRef(entity.getLatitudeRef())
                     .latitudeRef(entity.getLatitudeRef())
                     .mediaType(mediaTypeEnum.getVal())
                     .mediaType(mediaTypeEnum.getVal())
@@ -396,6 +411,40 @@ public class FileServiceImpl implements IFileService {
         return builder.build();
         return builder.build();
     }
     }
 
 
+    private String getThumbnailURL(MediaFileEntity entity) {
+        String originFileName = entity.getFileName();
+        //缩略图路径
+        String tObjectKey = getThumbnailObjectKey(originFileName);
+        putThumbnailImage(tObjectKey,entity.getObjectKey());
+        return ossService.getObjectUrl(OssConfiguration.bucket, tObjectKey).toString();
+
+    }
+
+    private void putThumbnailImage(String tObjectKey, String originObjectKey) {
+        if(originObjectKey.endsWith(PicExifUtil.MP4)) {
+            System.out.println(originObjectKey);
+        }
+        //生成缩略图
+        if(!ossService.objectExists(OssConfiguration.bucket,tObjectKey)) {
+            BufferedImage bufferedImage = ThumbnailatorUtil.getThumbnail(originObjectKey,100,100);
+            if(bufferedImage != null) {
+                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+                try {
+                    ImageIO.write(bufferedImage, JPEG, outputStream);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+                ossService.putObject(OssConfiguration.bucket,tObjectKey,new ByteArrayInputStream(outputStream.toByteArray()));
+            }
+        }
+    }
+
+    private String getThumbnailObjectKey(String originFileName) {
+        String[] nameSplit = originFileName.split(SPLIT_DOT);
+        //缩略图路径
+        return T_PATH + nameSplit[0] + TAIL + DOT + PicExifUtil.JPG;
+    }
+
     private MediaTypeEnum convertMediaType(MediaFileEntity entity) {
     private MediaTypeEnum convertMediaType(MediaFileEntity entity) {
         if(StringUtils.hasText(entity.getMediaType())) {
         if(StringUtils.hasText(entity.getMediaType())) {
             if (entity.getMediaType().startsWith(IMAGE)) {
             if (entity.getMediaType().startsWith(IMAGE)) {
@@ -544,4 +593,52 @@ public class FileServiceImpl implements IFileService {
                 .collect(Collectors.toMap(a -> a.getDirId(), MediaFileSumEntity::getSumSize));
                 .collect(Collectors.toMap(a -> a.getDirId(), MediaFileSumEntity::getSumSize));
     }
     }
 
 
+    @Override
+    public Boolean updateFile(MediaFileDTO mediaFileDTO) {
+        int update = mapper.update(this.dtoToEntity(mediaFileDTO),
+                new LambdaUpdateWrapper<MediaFileEntity>().eq(MediaFileEntity::getFileId, mediaFileDTO.getFileId()));
+        return update > 0;
+    }
+
+    private MediaFileEntity dtoToEntity(MediaFileDTO mediaFileDTO) {
+        MediaFileEntity.MediaFileEntityBuilder builder = MediaFileEntity.builder();
+
+        if (mediaFileDTO != null) {
+            builder.fileName(mediaFileDTO.getFileName())
+                    .fileId(mediaFileDTO.getFileId())
+                    .filePath(mediaFileDTO.getFilePath())
+                    .isOriginal(mediaFileDTO.getIsOriginal())
+                    .fingerprint(mediaFileDTO.getFingerprint())
+                    .objectKey(mediaFileDTO.getObjectKey())
+                    .tinnyFingerprint(mediaFileDTO.getTinnyFingerprint())
+                    .payload(mediaFileDTO.getPayload())
+                    .createTime(mediaFileDTO.getCreateTime() != null ?
+                            mediaFileDTO.getCreateTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : null)
+                    .drone(mediaFileDTO.getDrone())
+                    .jobId(mediaFileDTO.getJobId())
+                    .dirId(mediaFileDTO.getDirId())
+                    .waylineName(mediaFileDTO.getWaylineName())
+                    .size(mediaFileDTO.getSize())
+                    .longitude(mediaFileDTO.getLongitude())
+                    .latitude(mediaFileDTO.getLatitude())
+                    .imageWidth(mediaFileDTO.getImageWidth())
+                    .imageHeight(mediaFileDTO.getImageHeight())
+                    .absoluteAltitude(mediaFileDTO.getAbsoluteAltitude())
+                    .gimbalYawDegree(mediaFileDTO.getGimbalYawDegree())
+                    .relativeAltitude(mediaFileDTO.getRelativeAltitude())
+                    .taskName(mediaFileDTO.getTaskName())
+                    .sourceFrom(mediaFileDTO.getSourceFrom())
+                    .pictureTime(mediaFileDTO.getPictureTime() != null ?
+                            mediaFileDTO.getPictureTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : null)
+                    .xResolution(mediaFileDTO.getXResolution())
+                    .yResolution(mediaFileDTO.getYResolution())
+                    .longitudeRef(mediaFileDTO.getLongitudeRef())
+                    .latitudeRef(mediaFileDTO.getLatitudeRef())
+                    .pictureType(mediaFileDTO.getPictureType())
+                    .durationSeconds(mediaFileDTO.getDurationSeconds());
+        }
+
+        return builder.build();
+    }
+
 }
 }