Преглед изворни кода

提交地磅计量初始化

chenxiaofei пре 4 месеци
родитељ
комит
897b65bfed

+ 53 - 37
iot-platform-manager/src/main/java/com/platform/api/manager/WeighbridgeRecordManage.java

@@ -14,6 +14,8 @@ import com.platform.utils.FileUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.core.task.TaskExecutor;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
@@ -23,6 +25,7 @@ import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
 
 /**
  * 地磅记录业务编排类
@@ -37,6 +40,9 @@ public class WeighbridgeRecordManage {
 
     private final ValidateLicensePlateService validateLicensePlateService;
 
+    @Qualifier("taskExecutor")
+    private final TaskExecutor taskExecutor;
+
     /**
      * 处理地磅过磅数据上报
      * @param request 地磅上报请求参数
@@ -141,24 +147,57 @@ public class WeighbridgeRecordManage {
     }
 
     /**
-     * 异步处理图片文件上传
+     * 异步处理图片文件上传(真正的并行上传)
+     * 为每个图片创建独立的异步任务,实现并行上传
      */
     @Async("taskExecutor")
     public CompletableFuture<String> processImageFilesAsync(MultipartFile[] images) {
-        List<String> resultList = new ArrayList<>();
-        Arrays.stream(images).forEach(image -> {
-            String ossUrl = null;
-            try {
-                ossUrl = FileUtils.uploadFile(image);
-            } catch (Exception e) {
-                log.error("上传文件异常", e);
-                throw new IotException(ErrorCodeEnum.SYSTEM_ERROR, "上传文件异常");
-            }
-            if (StringUtils.isNotBlank(ossUrl)) {
-                resultList.add(ossUrl);
-            }
+        log.info("开始并行上传 {} 张图片", images.length);
+        long startTime = System.currentTimeMillis();
+        
+        // 为每个图片创建独立的异步上传任务
+        List<CompletableFuture<String>> uploadTasks = Arrays.stream(images)
+                .map(image -> CompletableFuture.supplyAsync(() -> {
+                    String fileName = image.getOriginalFilename();
+                    log.debug("开始上传图片: {}", fileName);
+                    try {
+                        String ossUrl = FileUtils.uploadFile1(image);
+                        if (StringUtils.isNotBlank(ossUrl)) {
+                            log.debug("图片上传成功: {} -> {}", fileName, ossUrl);
+                            return ossUrl;
+                        } else {
+                            log.warn("图片上传返回空URL: {}", fileName);
+                            return null;
+                        }
+                    } catch (Exception e) {
+                        log.error("上传图片失败: {}", fileName, e);
+                        // 不抛出异常,返回 null,让其他图片继续上传
+                        return null;
+                    }
+                }, taskExecutor))  // 使用线程池执行
+                .collect(Collectors.toList());
+
+        // 等待所有上传任务完成
+        CompletableFuture<Void> allOf = CompletableFuture.allOf(
+                uploadTasks.toArray(new CompletableFuture[0])
+        );
+
+        // 收集所有成功上传的 URL
+        return allOf.thenApply(v -> {
+            List<String> successUrls = uploadTasks.stream()
+                    .map(CompletableFuture::join)  // 获取每个任务的结果
+                    .filter(StringUtils::isNotBlank)  // 过滤掉失败的(null)
+                    .collect(Collectors.toList());
+
+            long endTime = System.currentTimeMillis();
+            log.info("图片并行上传完成 - 总数: {}, 成功: {}, 失败: {}, 耗时: {}ms", 
+                    images.length, 
+                    successUrls.size(), 
+                    images.length - successUrls.size(),
+                    endTime - startTime);
+
+            return String.join(",", successUrls);
         });
-        return CompletableFuture.completedFuture(String.join(",", resultList));
     }
     /**
      * 异步更新图片URL
@@ -172,29 +211,6 @@ public class WeighbridgeRecordManage {
         weighbridgeRecordService.updateById(updateRecord);
     }
 
-    /**
-     * 处理图片文件,提取文件名并拼接
-     * @param images 图片文件数组
-     * @return 逗号分隔的文件名字符串
-     */
-    private String processImageFiles(MultipartFile[] images) {
-        List<String> resultList = new ArrayList<>();
-         Arrays.stream(images).forEach(x->{
-                     String oosUrl = null;
-                     //上传文件是否成功
-                     try {
-                         oosUrl = FileUtils.uploadFile(x);
-                     } catch (Exception e) {
-                         log.error("上传文件异常", e);
-                         throw new IotException(ErrorCodeEnum.SYSTEM_ERROR, "上传文件异常");
-                     }
-                     if (StringUtils.isNotBlank(oosUrl)) {
-                         resultList.add(oosUrl);
-                     };
-                });
-         return String.join(",", resultList);
-    }
-
     /**
      * 时间戳转换:自动识别秒/毫秒
      * @param timestamp 时间戳(秒或毫秒)

+ 56 - 0
iot-platform-manager/src/main/java/com/platform/utils/FileUtils.java

@@ -343,6 +343,62 @@ public class FileUtils {
             return null;
         }
     }
+    public static String uploadFile1(MultipartFile file) {
+        // 立即将文件内容读取到内存中,避免异步处理时临时文件被删除
+        byte[] fileBytes;
+        try {
+            fileBytes = file.getBytes(); // 使用 getBytes() 预先读取文件内容
+        } catch (IOException e) {
+            log.error("读取文件内容失败", e);
+            return null;
+        }
+
+        // 私有云要关闭CNAME
+        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
+        conf.setSupportCname(false);
+
+        try {
+            //创建OSSClient实例
+            defaultOss();
+            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+
+            //容器不存在,就创建
+            if (!ossClient.doesBucketExist(bucketName)) {
+                ossClient.createBucket(bucketName);
+                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
+                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
+                ossClient.createBucket(createBucketRequest);
+            }
+
+            String fileName = file.getOriginalFilename();
+            //生成随机唯一值,使用uuid,添加到文件名称里面
+            fileName = PasswordUtils.md5(fileName);
+            //按照当前日期,创建文件夹,上传到创建文件夹里面
+            String timeUrl = new DateTime().toString("yyyyMMdd");
+            fileName = timeUrl + "/" + fileName;
+            String filePath = BASE_DIR + fileName;
+            /**设置上传内容类型*/
+            ObjectMetadata objectMeta = new ObjectMetadata();
+            objectMeta.setContentType(FileUtils.getContentTypeByOSS(file.getOriginalFilename()));
+
+            // 使用字节数组创建输入流,避免临时文件依赖
+            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileBytes);
+
+            //调用方法实现上传
+            ossClient.putObject(bucketName, filePath, byteArrayInputStream, objectMeta);
+
+            //关闭OSSClient。
+            ossClient.shutdown();
+            //上传之后文件路径
+            String url = "https://" + bucketName + "." + endpoint + "/" + filePath;
+            //返回 上传文件地址
+            return url;
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error("oss-upload-file-error:{}", e.getMessage(), e);
+            return null;
+        }
+    }
 
     /**
      * 文件上传