|
@@ -14,6 +14,8 @@ import com.platform.utils.FileUtils;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
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.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
@@ -23,6 +25,7 @@ import java.time.LocalDateTime;
|
|
|
import java.time.ZoneId;
|
|
import java.time.ZoneId;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.CompletableFuture;
|
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 地磅记录业务编排类
|
|
* 地磅记录业务编排类
|
|
@@ -37,6 +40,9 @@ public class WeighbridgeRecordManage {
|
|
|
|
|
|
|
|
private final ValidateLicensePlateService validateLicensePlateService;
|
|
private final ValidateLicensePlateService validateLicensePlateService;
|
|
|
|
|
|
|
|
|
|
+ @Qualifier("taskExecutor")
|
|
|
|
|
+ private final TaskExecutor taskExecutor;
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 处理地磅过磅数据上报
|
|
* 处理地磅过磅数据上报
|
|
|
* @param request 地磅上报请求参数
|
|
* @param request 地磅上报请求参数
|
|
@@ -141,24 +147,57 @@ public class WeighbridgeRecordManage {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 异步处理图片文件上传
|
|
|
|
|
|
|
+ * 异步处理图片文件上传(真正的并行上传)
|
|
|
|
|
+ * 为每个图片创建独立的异步任务,实现并行上传
|
|
|
*/
|
|
*/
|
|
|
@Async("taskExecutor")
|
|
@Async("taskExecutor")
|
|
|
public CompletableFuture<String> processImageFilesAsync(MultipartFile[] images) {
|
|
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
|
|
* 异步更新图片URL
|
|
@@ -172,29 +211,6 @@ public class WeighbridgeRecordManage {
|
|
|
weighbridgeRecordService.updateById(updateRecord);
|
|
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 时间戳(秒或毫秒)
|
|
* @param timestamp 时间戳(秒或毫秒)
|