|
|
@@ -0,0 +1,110 @@
|
|
|
+package com.platform.api.manager;
|
|
|
+
|
|
|
+import com.platform.enums.ErrorCodeEnum;
|
|
|
+import com.platform.exception.IotException;
|
|
|
+import com.platform.utils.FileUtils;
|
|
|
+import lombok.Data;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.io.*;
|
|
|
+import java.util.concurrent.CompletableFuture;
|
|
|
+
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class UploadService {
|
|
|
+ /**
|
|
|
+ * 异步处理图片文件上传(真正的并行上传)
|
|
|
+ * 为每个图片创建独立的异步任务,实现并行上传
|
|
|
+ */
|
|
|
+
|
|
|
+ @Async("taskExecutor")
|
|
|
+ public CompletableFuture<String> processImageFilesAsync(List<byte[]> imageBytesList, String licensePlate){
|
|
|
+ List<String> resultList = new ArrayList<>();
|
|
|
+ for (byte[] imageBytes : imageBytesList) {
|
|
|
+ String ossUrl = null;
|
|
|
+ try {
|
|
|
+ // 将字节数组包装成MultipartFile进行上传
|
|
|
+ String filename = "image" + System.currentTimeMillis() + ".jpg";
|
|
|
+ MultipartFile multipartFile = new CustomMockMultipartFile(
|
|
|
+ filename,
|
|
|
+ filename,
|
|
|
+ "image/jpeg",
|
|
|
+ imageBytes
|
|
|
+ );
|
|
|
+ ossUrl = FileUtils.uploadFile(multipartFile);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("上传文件异常,车牌号: {}", licensePlate, e);
|
|
|
+ throw new IotException(ErrorCodeEnum.SYSTEM_ERROR, "上传文件异常");
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotBlank(ossUrl)) {
|
|
|
+ resultList.add(ossUrl);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return CompletableFuture.completedFuture(String.join(",", resultList));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 用于将字节数组包装成MultipartFile的辅助类
|
|
|
+ */
|
|
|
+ private static class CustomMockMultipartFile implements MultipartFile {
|
|
|
+ private final String name;
|
|
|
+ private final String originalFilename;
|
|
|
+ private final String contentType;
|
|
|
+ private final byte[] bytes;
|
|
|
+
|
|
|
+ public CustomMockMultipartFile(String name, String originalFilename, String contentType, byte[] bytes) {
|
|
|
+ this.name = name;
|
|
|
+ this.originalFilename = originalFilename;
|
|
|
+ this.contentType = contentType;
|
|
|
+ this.bytes = bytes;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getName() {
|
|
|
+ return name;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getOriginalFilename() {
|
|
|
+ return originalFilename;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getContentType() {
|
|
|
+ return contentType;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean isEmpty() {
|
|
|
+ return bytes == null || bytes.length == 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public long getSize() {
|
|
|
+ return bytes.length;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public byte[] getBytes() throws IOException {
|
|
|
+ return bytes;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public InputStream getInputStream() throws IOException {
|
|
|
+ return new ByteArrayInputStream(bytes);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void transferTo(File dest) throws IOException, IllegalStateException {
|
|
|
+ try (FileOutputStream fos = new FileOutputStream(dest)) {
|
|
|
+ fos.write(bytes);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|