|
|
@@ -5,7 +5,6 @@ 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;
|
|
|
@@ -17,13 +16,10 @@ 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;
|
|
|
|
|
|
/**
|
|
|
* 二期-文件上传
|
|
|
@@ -128,143 +124,77 @@ public class FileUploadUtil {
|
|
|
* @return List<String>
|
|
|
*/
|
|
|
public List<String> uploadMoreFile(MultipartRequest multipartRequest) {
|
|
|
- long startTime = System.currentTimeMillis();
|
|
|
try {
|
|
|
log.info("FileUpload.uploadMoreFile multipartRequest={}", multipartRequest.getFileNames());
|
|
|
- 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);
|
|
|
- }
|
|
|
+ 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")));
|
|
|
}
|
|
|
}
|
|
|
return filePathList;
|
|
|
@@ -275,53 +205,6 @@ 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 文件
|