Procházet zdrojové kódy

另外一种方案,暂时注释掉截取第一针,第二次提交

liudongzhi před 1 měsícem
rodič
revize
afcb5eb855

+ 186 - 69
alien-store/src/main/java/shop/alien/store/util/FileUploadUtil.java

@@ -5,6 +5,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.MultipartRequest;
@@ -16,10 +17,13 @@ import shop.alien.util.common.VideoUtils;
 import shop.alien.util.file.FileUtil;
 
 import java.io.File;
+import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * 二期-文件上传
@@ -124,77 +128,143 @@ public class FileUploadUtil {
      * @return List<String>
      */
     public List<String> uploadMoreFile(MultipartRequest multipartRequest) {
+        long startTime = System.currentTimeMillis();
         try {
             log.info("FileUpload.uploadMoreFile multipartRequest={}", multipartRequest.getFileNames());
-            Set<String> fileNameSet = multipartRequest.getMultiFileMap().keySet();
-            List<String> filePathList = new ArrayList<>();
-            for (String s : fileNameSet) {
-                MultipartFile multipartFile = multipartRequest.getFileMap().get(s);
-                log.info("FileUpload.uploadMoreFile fileName={}", multipartFile.getOriginalFilename());
-                String uploadDir = this.uploadDir.replace("file:///", "").replace("\\", "/");
-                String prefix;
-                Map<String, String> fileNameAndType = FileUtil.getFileNameAndType(multipartFile);
-                //区分文件类型
-                if (imageFileType.contains(fileNameAndType.get("type").toLowerCase())) {
-                    uploadDir += "/image";
-                    prefix = "image/";
-                    log.info("FileUpload.uploadMoreFile 获取到图片文件准备复制 {} {} {}", uploadDir, prefix, multipartFile.getOriginalFilename());
-                    // 去除文件名中的逗号,避免URL拼接时被错误分割
-                    String imageFileName = fileNameAndType.get("name").replaceAll(",", "");
-                    filePathList.add(aliOSSUtil.uploadFile(multipartFile, prefix + imageFileName + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type")));
-                    ;
-                } else if (videoFileType.contains(fileNameAndType.get("type").toLowerCase())) {
-                    uploadDir += "/video/";
-                    prefix = "video/";
-                    //上传视频文件
-                    log.info("FileUpload.uploadMoreFile 获取到视频文件准备复制 {} {} {}", uploadDir, prefix, multipartFile.getOriginalFilename());
-                    // 去除文件名中的逗号,避免URL拼接时被错误分割
-                    String videoFileName = fileNameAndType.get("name").replaceAll(",", "") + RandomCreateUtil.getRandomNum(6);
-                    String cacheVideoPath = copyFile(uploadDir, multipartFile);
-                    filePathList.add(aliOSSUtil.uploadFile(multipartFile, prefix + videoFileName + "." + fileNameAndType.get("type")));
-                    //缓存视频截图使用
-//                    File videoFile = new File(cacheVideoPath);
-//                    //获取视频某帧截图
-//                    log.info("FileUpload.uploadMoreFile 视频文件复制完毕, 获取第一秒图片 {}", videoFile.getName());
-//                    String videoPath = videoUtils.getImg(uploadDir + videoFile.getName());
-//                    log.info("FileUpload.uploadMoreFile 视频文件复制完毕, 图片位置 {}", videoPath);
-//                    if (!videoPath.isEmpty()) {
-//                        File videoImgFile = new File(videoPath);
-//                        Map<String, String> videoImg = FileUtil.getFileNameAndType(videoImgFile);
-//                        filePathList.add(aliOSSUtil.uploadFile(videoImgFile, prefix + videoFileName + "." + videoImg.get("type")));
-//                        videoImgFile.delete();
-//                        videoFile.delete();
-//                    } else {
-//                        throw new RuntimeException("视频截图失败");
-//                    }
-                } else if (voiceFileType.contains(fileNameAndType.get("type").toLowerCase())) {
-                    uploadDir += "/voice";
-                    prefix = "voice/";
-                    log.info("FileUpload.uploadMoreFile 获取到语音文件准备复制 {} {} {}", uploadDir, prefix, multipartFile.getOriginalFilename());
-                    // 去除文件名中的逗号,避免URL拼接时被错误分割
-                    String voiceFileName = fileNameAndType.get("name").replaceAll(",", "");
-                    filePathList.add(aliOSSUtil.uploadFile(multipartFile, prefix + voiceFileName + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type")));
-                } else if (privacyFileType.contains(fileNameAndType.get("type").toLowerCase())) {
-                    uploadDir += "/privacy/";
-                    prefix = "privacy/";
-                    log.info("FileUpload.uploadMoreFile 获取到隐私文件准备复制 {} {} {}", uploadDir, prefix, multipartFile.getOriginalFilename());
-                    // 去除文件名中的逗号,避免URL拼接时被错误分割
-                    String privacyFileName = fileNameAndType.get("name").replaceAll(",", "");
-                    filePathList.add(aliOSSUtil.uploadFile(multipartFile, prefix + privacyFileName + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type")));
-                } else if (pdfFileType.contains(fileNameAndType.get("type").toLowerCase())) {
-                    uploadDir += "/pdf";
-                    prefix = "pdf/";
-                    log.info("FileUpload.uploadMoreFile 获取到PDF文件准备复制 {} {} {}", uploadDir, prefix, multipartFile.getOriginalFilename());
-                    // 去除文件名中的逗号,避免URL拼接时被错误分割
-                    String pdfFileName = fileNameAndType.get("name").replaceAll(",", "");
-                    filePathList.add(aliOSSUtil.uploadFile(multipartFile, prefix + pdfFileName + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type")));
-                } else if (ohterFileType.contains(fileNameAndType.get("type").toLowerCase())) {
-                    uploadDir += "/other/";
-                    prefix = "other/";
-                    log.info("FileUpload.uploadMoreFile 获取到其他文件准备复制 {} {} {}", uploadDir, prefix, multipartFile.getOriginalFilename());
-                    // 去除文件名中的逗号,避免URL拼接时被错误分割
-                    String otherFileName = fileNameAndType.get("name").replaceAll(",", "");
-                    filePathList.add(aliOSSUtil.uploadFile(multipartFile, prefix + otherFileName + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type")));
+            Collection<MultipartFile> files = multipartRequest.getFileMap().values();
+
+            if (files.isEmpty()) {
+                return Collections.emptyList();
+            }
+
+            String baseUploadDir = this.uploadDir.replace("file:///", "").replace("\\", "/");
+
+            // 如果只有一个文件,直接处理(避免线程池开销)
+            if (files.size() == 1) {
+                MultipartFile file = files.iterator().next();
+                return processSingleFileForUploadMore(file, baseUploadDir);
+            }
+
+            // 多个文件使用并行流处理
+            List<String> filePathList = files.parallelStream()
+                    .flatMap(file -> {
+                        try {
+                            return processSingleFileForUploadMore(file, baseUploadDir).stream();
+                        } catch (Exception e) {
+                            log.error("处理文件失败: {}", file.getOriginalFilename(), e);
+                            return Stream.empty();
+                        }
+                    })
+                    .collect(Collectors.toList());
+
+            long totalTime = System.currentTimeMillis() - startTime;
+            log.info("批量文件上传完成,文件数: {}, 总耗时: {} ms", files.size(), totalTime);
+
+            return filePathList;
+        } catch (Exception e) {
+            log.error("FileUpload.uploadMoreFile ERROR Msg={}", e.getMessage(), e);
+            throw new RuntimeException("批量文件上传失败: " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 处理单个文件(用于 uploadMoreFile)
+     *
+     * @param multipartFile 文件
+     * @param baseUploadDir 基础上传目录
+     * @return 文件URL列表(视频会包含视频URL和截图URL)
+     */
+    private List<String> processSingleFileForUploadMore(MultipartFile multipartFile, String baseUploadDir) {
+        List<String> filePathList = new ArrayList<>();
+        File tempVideoFile = null;
+
+        try {
+            Map<String, String> fileNameAndType = FileUtil.getFileNameAndType(multipartFile);
+            String fileType = fileNameAndType.get("type").toLowerCase();
+            String prefix;
+            String uploadDir = baseUploadDir;
+
+            // 区分文件类型并处理
+            if (imageFileType.contains(fileType)) {
+                prefix = "image/";
+                String imageFileName = fileNameAndType.get("name").replaceAll(",", "");
+                String ossFilePath = prefix + imageFileName + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type");
+                // 直接流式上传
+                try (InputStream inputStream = multipartFile.getInputStream()) {
+                    String url = aliOSSUtil.uploadFile(inputStream, ossFilePath);
+                    if (url != null) {
+                        filePathList.add(url);
+                    }
+                }
+
+            } else if (videoFileType.contains(fileType)) {
+                prefix = "video/";
+                uploadDir += "/video/";
+                String videoFileName = fileNameAndType.get("name").replaceAll(",", "") + RandomCreateUtil.getRandomNum(6);
+                String ossFilePath = prefix + videoFileName + "." + fileNameAndType.get("type");
+
+                // 视频需要截图,先保存文件
+                String tempPath = copyFile(uploadDir, multipartFile);
+                tempVideoFile = new File(tempPath);
+                if (!tempVideoFile.exists() || tempVideoFile.length() == 0) {
+                    throw new RuntimeException("视频文件保存失败: " + tempPath);
+                }
+
+                // 从文件上传视频
+                String videoUrl = aliOSSUtil.uploadFile(tempVideoFile, ossFilePath);
+                if (videoUrl != null) {
+                    filePathList.add(videoUrl);
+                }
+
+                // 异步处理视频截图
+                processVideoScreenshotAsync(tempVideoFile, videoFileName, prefix, uploadDir);
+
+            } else if (voiceFileType.contains(fileType)) {
+                prefix = "voice/";
+                String voiceFileName = fileNameAndType.get("name").replaceAll(",", "");
+                String ossFilePath = prefix + voiceFileName + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type");
+                // 直接流式上传
+                try (InputStream inputStream = multipartFile.getInputStream()) {
+                    String url = aliOSSUtil.uploadFile(inputStream, ossFilePath);
+                    if (url != null) {
+                        filePathList.add(url);
+                    }
+                }
+
+            } else if (privacyFileType.contains(fileType)) {
+                prefix = "privacy/";
+                String privacyFileName = fileNameAndType.get("name").replaceAll(",", "");
+                String ossFilePath = prefix + privacyFileName + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type");
+                // 直接流式上传
+                try (InputStream inputStream = multipartFile.getInputStream()) {
+                    String url = aliOSSUtil.uploadFile(inputStream, ossFilePath);
+                    if (url != null) {
+                        filePathList.add(url);
+                    }
+                }
+
+            } else if (pdfFileType.contains(fileType)) {
+                prefix = "pdf/";
+                String pdfFileName = fileNameAndType.get("name").replaceAll(",", "");
+                String ossFilePath = prefix + pdfFileName + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type");
+                // 直接流式上传
+                try (InputStream inputStream = multipartFile.getInputStream()) {
+                    String url = aliOSSUtil.uploadFile(inputStream, ossFilePath);
+                    if (url != null) {
+                        filePathList.add(url);
+                    }
+                }
+
+            } else if (ohterFileType.contains(fileType)) {
+                prefix = "other/";
+                String otherFileName = fileNameAndType.get("name").replaceAll(",", "");
+                String ossFilePath = prefix + otherFileName + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type");
+                // 直接流式上传
+                try (InputStream inputStream = multipartFile.getInputStream()) {
+                    String url = aliOSSUtil.uploadFile(inputStream, ossFilePath);
+                    if (url != null) {
+                        filePathList.add(url);
+                    }
                 }
             }
             return filePathList;
@@ -205,6 +275,53 @@ public class FileUploadUtil {
     }
 
     /**
+     * 异步处理视频截图
+     *
+     * @param tempVideoFile 临时视频文件
+     * @param videoFileName 视频文件名(不含扩展名)
+     * @param prefix OSS路径前缀
+     * @param uploadDir 上传目录
+     */
+    @Async
+    protected void processVideoScreenshotAsync(File tempVideoFile, String videoFileName, String prefix, String uploadDir) {
+        try {
+            log.info("开始异步处理视频截图: {}", tempVideoFile.getName());
+
+            // 获取视频截图
+            String screenshotPath = videoUtils.getImg(uploadDir + tempVideoFile.getName());
+
+            if (screenshotPath != null && !screenshotPath.isEmpty()) {
+                File screenshotFile = new File(screenshotPath);
+                if (screenshotFile.exists()) {
+                    try {
+                        // 上传截图到OSS
+                        Map<String, String> screenshotInfo = FileUtil.getFileNameAndType(screenshotFile);
+                        String screenshotUrl = aliOSSUtil.uploadFile(screenshotFile, prefix + videoFileName + "." + screenshotInfo.get("type"));
+
+                        log.info("视频截图上传成功: {} -> {}", tempVideoFile.getName(), screenshotUrl);
+                    } finally {
+                        // 清理临时截图文件
+                        screenshotFile.delete();
+                    }
+                } else {
+                    log.warn("视频截图文件不存在: {}", screenshotPath);
+                }
+            } else {
+                log.warn("视频截图失败: {}", tempVideoFile.getName());
+            }
+
+        } catch (Exception e) {
+            log.error("异步处理视频截图失败: {}", tempVideoFile.getName(), e);
+        } finally {
+            // 清理临时视频文件
+            if (tempVideoFile != null && tempVideoFile.exists()) {
+                tempVideoFile.delete();
+            }
+        }
+    }
+
+
+    /**
      * 上传图片
      *
      * @param multipartRequest 文件