From 14821e28286d773ad5ff2c13510e39c5eb117daf Mon Sep 17 00:00:00 2001
From: kongzy <kongzy>
Date: 星期五, 05 七月 2024 13:46:32 +0800
Subject: [PATCH] update

---
 exam-system/src/main/java/com/gkhy/exam/system/service/impl/SysCommonServiceImpl.java |  191 +++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 156 insertions(+), 35 deletions(-)

diff --git a/exam-system/src/main/java/com/gkhy/exam/system/service/impl/SysCommonServiceImpl.java b/exam-system/src/main/java/com/gkhy/exam/system/service/impl/SysCommonServiceImpl.java
index 0ccb5d1..2ee2b25 100644
--- a/exam-system/src/main/java/com/gkhy/exam/system/service/impl/SysCommonServiceImpl.java
+++ b/exam-system/src/main/java/com/gkhy/exam/system/service/impl/SysCommonServiceImpl.java
@@ -1,13 +1,19 @@
 package com.gkhy.exam.system.service.impl;
 
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.io.FileUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.gkhy.exam.common.config.FilePathConfig;
+import com.gkhy.exam.common.enums.ResourceTypeEnum;
 import com.gkhy.exam.common.exception.ApiException;
-import com.gkhy.exam.common.utils.M3u8Utils;
-import com.gkhy.exam.common.utils.MinioUtils;
+import com.gkhy.exam.common.utils.*;
+import com.gkhy.exam.system.domain.ExResource;
 import com.gkhy.exam.system.domain.vo.UploadObjectVO;
+import com.gkhy.exam.system.mapper.ExResourceMapper;
 import com.gkhy.exam.system.service.SysCommonService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@@ -17,9 +23,9 @@
 import sun.misc.BASE64Decoder;
 
 import javax.annotation.Resource;
-import javax.servlet.http.HttpServletRequest;
 import java.io.*;
-import java.time.LocalDateTime;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.*;
 import java.util.concurrent.CountDownLatch;
 
@@ -33,13 +39,17 @@
     private M3u8Utils m3u8Utils;
     @Autowired
     private MinioUtils minioUtils;
+    @Autowired
+    private ExResourceMapper resourceMapper;
     @Resource
-    private FilePathConfig filePath;
+    private FilePathConfig filePathConfig;
+
+    // 使用HashSet存储允许的文件格式,提高查找效率
+    private final HashSet<String> FORMATSET = new HashSet<>(Arrays.asList(".mp4", ".mp3", ".xls", ".xlsx", ".doc", ".docx", ".ppt", ".pptx", ".pdf"));
+
 
     @Resource(name = "threadPoolTaskExecutor")
     private ThreadPoolTaskExecutor poolTaskExecutor;
-
-    String projectUrl = System.getProperty("user.dir").replaceAll("\\\\", "/");
 
     @Override
     public UploadObjectVO uploadFile(MultipartFile file) {
@@ -68,7 +78,16 @@
     @Override
     public String uploadVideo2M3u8(MultipartFile file) throws Exception {
         String path=m3u8Utils.mediaFileToM3u8(file);
-        return upload2M3u8(path);
+        String name= upload2M3u8(path,null);
+        if(StringUtils.isBlank(name)){
+            throw new ApiException("文件上传失败");
+        }
+        return name;
+    }
+
+    public String localVideo2M3u8(String path,String mainName) throws Exception {
+        String paths=m3u8Utils.localFileToM3u8(path,mainName);
+        return upload2M3u8(paths,mainName);
     }
 
 
@@ -78,7 +97,7 @@
      * @return 路径
      * @throws Exception
      */
-    public String upload2M3u8(String path) throws Exception {
+    public synchronized String upload2M3u8(String path,String filePrex) throws Exception {
         //存储转码后文件
         String realPath = path.substring(0, path.lastIndexOf("/"));
         log.info("视频解析后的 realPath {}", realPath);
@@ -89,11 +108,10 @@
         if (null == files || files.length == 0) {
             return null;
         }
-        String patch = DateUtil.format(LocalDateTime.now(), "yyyy/MM/") + name.substring(0, name.lastIndexOf(".")) + "/";
         List<File> errorFile = new ArrayList<>();
-
         long start = System.currentTimeMillis();
-//        //替换m3u8文件中的路径
+        //替换m3u8文件中的路径
+
 //        FileUtil.replaceTextContent(path, name.substring(0, name.lastIndexOf(".")),
 //                aliOssProperties.getMyHostUrl() + filePath.getProxy() + patch +
 //                        name.substring(0, name.lastIndexOf(".")));
@@ -101,11 +119,15 @@
         CountDownLatch countDownLatch = new CountDownLatch(files.length);
         Arrays.stream(files).forEach(li -> poolTaskExecutor.execute(() -> {
             try (FileInputStream fileInputStream = new FileInputStream(li)) {
-                minioUtils.fileUploader(patch + li.getName(), fileInputStream);
-
+                String objectKey=li.getName();
+                if(StringUtils.isNotBlank(filePrex)){
+                    objectKey=filePrex+"/"+li.getName();
+                }
+                minioUtils.fileUploader(objectKey, fileInputStream);
                 log.info("文件:{} 正在上传", li.getName());
             } catch (Exception e) {
                 errorFile.add(li);
+                log.error("文件:{}上传失败",li.getName());
                 e.printStackTrace();
             } finally {
                 countDownLatch.countDown();
@@ -114,42 +136,141 @@
         countDownLatch.await();
         long end = System.currentTimeMillis();
         log.info("解析文件上传成功,共计:{} 个文件,失败:{},共耗时: {}ms", files.length, errorFile.size(), end - start);
-        //  try {
-        //      minioComponent.mkBucket("m3u8");
-        //  } catch (Exception e) {
-        //      log.error("创建Bucket失败!");
-        //  }
-
         //异步移除所有文件
         poolTaskExecutor.execute(() -> {
-            deleteFile(projectUrl+filePath.getTempPath());
+            FileUtil.del(realPath);
+            log.warn("临时目录 {}已删除", realPath);
         });
         if (CollectionUtils.isEmpty(errorFile)) {
-            return  filePath.getProxy() + patch + name;
+            return StringUtils.isNotBlank(filePrex)? filePrex+"/"+name:name;
         }
         return "";
     }
 
-    public static void deleteFile(String path){
-        File dest = new File(path);
-        if (dest.isFile() && dest.exists()) {
-            dest.delete();
+
+    @Override
+    public boolean uploadSlice( String fileMd5, String chunkName, MultipartFile file) {
+        String systemDir=System.getProperty("user.dir");
+        String filePath=systemDir+filePathConfig.getTempPath()+"chunk/"+fileMd5;
+        File dirFile=new File(filePath);
+        if(!dirFile.exists()){
+            dirFile.mkdirs();
+        }
+        filePath=filePath+File.separator+chunkName;
+        try {
+            file.transferTo(new File(filePath));
+        } catch (FileNotFoundException e) {
+            throw new ApiException("找不到文件");
+        } catch (IOException e) {
+            throw new ApiException("发生错误,请联系管理员");
+        }
+        return false;
+    }
+
+
+    @Override
+    public UploadObjectVO uploadMerge(String fileMd5, String fileName) throws Exception {
+        String subfix=fileName.substring(fileName.lastIndexOf("."),fileName.length());
+        checkFileFormat(subfix);
+        UploadObjectVO uploadObjectVO=mergeFile(fileMd5,fileName);
+        String localPath=uploadObjectVO.getPath();
+        String minioPath="";
+        if(".mp4".equalsIgnoreCase(subfix)){
+            String m3u8Path=m3u8Utils.localFileToM3u8(localPath, fileMd5);
+            //计算mp4时长
+            uploadObjectVO.setResourceLength(VideoUtils.getMp4Duration(m3u8Path));
+            uploadObjectVO.setResourceType(ResourceTypeEnum.VIDEO.getCode());
+            minioPath= upload2M3u8(m3u8Path,fileMd5);
+        }else{
+            if(".mp3".equalsIgnoreCase(subfix)){
+                uploadObjectVO.setResourceType(ResourceTypeEnum.AUDIO.getCode());
+                //计算mp3时长
+                uploadObjectVO.setResourceLength(VideoUtils.getMp3Duration(localPath));
+            }else{
+                uploadObjectVO.setResourceType(ResourceTypeEnum.DOC.getCode());
+                //计算文件页数
+                uploadObjectVO.setDocPage(DocUtils.getDocPageCount(fileName,Files.newInputStream(Paths.get(localPath))));
+            }
+            minioPath=minioUtils.fileUploader(uploadObjectVO.getFilename(), Files.newInputStream(Paths.get(localPath)));
+        }
+        if(StringUtils.isBlank(minioPath)){
+            throw new ApiException("上传文件失败");
+        }
+        //移除文件
+        poolTaskExecutor.execute(() -> {
+            FileUtil.del(new File(localPath).getParent());
+            log.warn("临时目录 {}已删除", new File(localPath).getParent());
+        });
+        uploadObjectVO.setPath(minioPath);
+        return uploadObjectVO;
+    }
+
+    private void checkFileFormat(String subfix){
+        if(!FORMATSET.contains(subfix)){
+            throw new ApiException(String.format("文件格式<%s>暂时不支持",subfix));
         }
     }
 
     @Override
-    public boolean uploadSlice(HttpServletRequest request, String guid, Integer chunk, MultipartFile file) {
-        return false;
+    public void removeMinioFile(Long resourceId,String path) {
+        String md5="";
+        if(path.indexOf("/")!=-1){
+            md5=path.substring(0,path.indexOf("/"));
+        }else{
+            md5=path.substring(0,path.lastIndexOf("."));
+        }
+        LambdaQueryWrapper<ExResource> lambdaQueryWrapper = Wrappers.<ExResource>lambdaQuery().
+                eq(true, ExResource::getMd5, md5);
+        if(resourceId!=null){
+            lambdaQueryWrapper.ne(ExResource::getId,resourceId);
+        }
+        lambdaQueryWrapper.last(" limit 1");
+        ExResource resource=resourceMapper.selectOne(lambdaQueryWrapper);
+        if(resource==null){//不存在共用md5文件
+            //删除minio文件
+            if(path.endsWith(".m3u8")){
+                minioUtils.removeFolder(md5);
+            }else{
+                minioUtils.removeFile(path);
+            }
+        }
     }
 
-    @Override
-    public String uploadVideoMerge(String guid, String fileName) {
-        return null;
-    }
+    public UploadObjectVO mergeFile(String fileMd5,String fileName){
+        String subfix = fileName.substring(fileName.lastIndexOf("."));
+        String systemDir=System.getProperty("user.dir");
+        String filePath=systemDir+filePathConfig.getTempPath()+"chunk/"+fileMd5;
 
-    @Override
-    public String uploadMerge(String guid, String fileName) {
-        return null;
+        File parentFileDir=new File(filePath);
+        if(!parentFileDir.exists()||!parentFileDir.isDirectory()){
+            throw new ApiException("切片文件合并失败,文件不存在");
+        }
+        String destPath=systemDir+filePathConfig.getTempPath()+fileMd5;
+        File destTempFile=new File(destPath,fileMd5+subfix);
+        if(!destTempFile.exists()){
+            destTempFile.getParentFile().mkdirs();
+        }
+        try{
+            //destTempFile.createNewFile();
+            for(int i=0;i<Objects.requireNonNull(parentFileDir.listFiles()).length;i++){
+                File partFile=new File(parentFileDir,fileMd5+"-"+i);
+                FileOutputStream destTempfos = new FileOutputStream(destTempFile, true);
+                //遍历"所有分片文件"到"最终文件"中
+                FileUtils.copyFile(partFile, destTempfos);
+                destTempfos.close();
+            }
+            FileUtil.del(parentFileDir);
+        }catch (Exception e){
+            log.error("切片文件合并,失败原因e:{}", e.getMessage());
+            throw new ApiException("切片文件合并失败:"+e.getMessage());
+        }
+        UploadObjectVO uploadObjectVO=new UploadObjectVO();
+        uploadObjectVO.setSize(destTempFile.length());
+        uploadObjectVO.setPath(destTempFile.getPath());
+        uploadObjectVO.setOriginName(fileName);
+        uploadObjectVO.setFilename(fileMd5+subfix);
+        uploadObjectVO.setMd5(fileMd5);
+        return uploadObjectVO;
     }
 
     @Override

--
Gitblit v1.9.2