diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/attach/AttachInfoService.java b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/attach/AttachInfoService.java new file mode 100644 index 0000000..773e929 --- /dev/null +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/attach/AttachInfoService.java @@ -0,0 +1,8 @@ +package net.northking.cctp.se.attach; + +public interface AttachInfoService { + + AttachmentDB save(String filename, String filePath, String tenantId, String objectId, String bizCode); + + AttachmentDB save(String filename, String filePath, String tenantId, int x, int y, String objectId, String bizCode); +} diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/attach/AttachInfoServiceImpl.java b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/attach/AttachInfoServiceImpl.java new file mode 100644 index 0000000..b7d84f4 --- /dev/null +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/attach/AttachInfoServiceImpl.java @@ -0,0 +1,43 @@ +package net.northking.cctp.se.attach; + + +import net.northking.cctp.se.repository.AttachmentInfoRepository; +import net.northking.cctp.se.util.AttachUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; + +@Service +public class AttachInfoServiceImpl implements AttachInfoService { + + private static final Logger logger = LoggerFactory.getLogger(AttachInfoServiceImpl.class); + + @Autowired + private AttachmentInfoRepository attachRepo; + + @Override + public AttachmentDB save(String filename, String filePath, String tenantId, String objectId, String bizCode) { + return save(filename, filePath, tenantId, -1, -1, objectId, bizCode); + } + + @Override + public AttachmentDB save(String filename, String filePath, String tenantId, int x, int y, String objectId, String bizCode) { + AttachmentDB attachmentDB = new AttachmentDB(); + attachmentDB.setId(AttachUtils.createId(filename)); + attachmentDB.setUrl(AttachUtils.exchangeToUrl(attachmentDB.getId(), tenantId)); + attachmentDB.setFilename(filename); + attachmentDB.setFilePath(filePath); + attachmentDB.setCreatedTime(new Date()); + attachmentDB.setTenantId(tenantId); + attachmentDB.setFailureTimes(0); + attachmentDB.setX(x); + attachmentDB.setY(y); + attachmentDB.setObjectId(objectId); + attachmentDB.setBizCode(bizCode); + attachRepo.saveAndFlush(attachmentDB); + return attachmentDB; + } +} diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/attach/AttachInfoUpload.java b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/attach/AttachInfoUpload.java new file mode 100644 index 0000000..76433ca --- /dev/null +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/attach/AttachInfoUpload.java @@ -0,0 +1,54 @@ +package net.northking.cctp.se.attach; + +import cn.hutool.core.bean.BeanUtil; +import net.northking.cctp.se.file.Attachment; +import net.northking.cctp.se.repository.AttachmentInfoRepository; +import net.northking.cctp.se.util.HttpUtils; +import net.northking.cctp.se.util.SpringUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 附件信息上传 + * + */ +public class AttachInfoUpload implements Runnable { + + private static final Logger logger = LoggerFactory.getLogger(AttachInfoUpload.class); + + private AttachmentDB attachmentDB; + + public AttachInfoUpload(AttachmentDB attachmentDB) { + this.attachmentDB = attachmentDB; + } + + @Override + public void run() { + if (attachmentDB.getX() > 0 && attachmentDB.getY() > 0) { + addSignature(); + } + AttachmentInfoRepository repo = SpringUtils.getBean(AttachmentInfoRepository.class); + try { + Attachment upload = HttpUtils.upload(attachmentDB.getFilePath(), + attachmentDB.getTenantId(), attachmentDB.getObjectId(), + attachmentDB.getBizCode(), attachmentDB.getId()); + if (upload != null && StringUtils.isNotBlank(upload.getUrlPath())) { + // 上传成功 + logger.debug("文件上传成功:{}, storagePath -> {}", BeanUtil.beanToMap(upload).toString(), attachmentDB.getId()); + // 删除数据库信息 + repo.deleteById(attachmentDB.getId()); + } + } catch (Exception e) { + logger.error("附件上传失败", e); + // 附件信息的失败次数加1,并更新数据库数据 + attachmentDB.setFailureTimes(attachmentDB.getFailureTimes() + 1); + repo.saveAndFlush(attachmentDB); + } + + } + + private void addSignature() { + // 根据信息添加红点或者其他标记 + } +} diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/attach/AttachmentDB.java b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/attach/AttachmentDB.java new file mode 100644 index 0000000..53bcebf --- /dev/null +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/attach/AttachmentDB.java @@ -0,0 +1,57 @@ +package net.northking.cctp.se.attach; + +import lombok.Data; +import lombok.ToString; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.Date; + +/** + * 附件对象 + */ +@Data +@Entity +@Table(name = "attachment_info") +@ToString +public class AttachmentDB { + // 格式:/yyyy/MM/dd/32位uuid.文件类型 + @Id + private String id; + // 格式: tenantId_yyyy_MM_dd_32位uuid.文件类型 + private String url; + + private String filename; + + private String filePath; + + /** + * 创建时间 + */ + private Date createdTime; + + /** + * 红点x坐标 + */ + private int x; + + /** + * 红点y坐标 + */ + private int y; + + /** + * 租户id + */ + private String tenantId; + + /** + * 上传失败次数 + */ + private int failureTimes; + + private String objectId; + + private String bizCode; +} diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/config/ExecutorPoolConfig.java b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/config/ExecutorPoolConfig.java index 4af873e..1eeec0a 100644 --- a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/config/ExecutorPoolConfig.java +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/config/ExecutorPoolConfig.java @@ -2,6 +2,7 @@ package net.northking.cctp.se.config; import com.google.common.annotations.VisibleForTesting; import lombok.Data; +import net.northking.cctp.se.thread.AttachInfoExecutorPool; import net.northking.cctp.se.thread.ExecutorPool; import net.northking.cctp.se.util.SpringUtils; import org.slf4j.Logger; @@ -26,6 +27,11 @@ public class ExecutorPoolConfig { return executorPool; } + @Bean + public AttachInfoExecutorPool createAttachInfoPool() { + AttachInfoExecutorPool pool = new AttachInfoExecutorPool(); + return pool; + } @ConfigurationProperties(prefix = "atu.engine.executor-pool") @Configuration diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/device/bean/PCDeviceConnection.java b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/device/bean/PCDeviceConnection.java index 64bc4c8..0ced1e8 100644 --- a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/device/bean/PCDeviceConnection.java +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/device/bean/PCDeviceConnection.java @@ -13,9 +13,12 @@ import net.northking.cctp.common.http.ResultWrapper; import net.northking.cctp.element.core.exception.ExecuteException; import net.northking.cctp.pc.driver.dto.EngineResultDto; import net.northking.cctp.pc.driver.socket.PCDriver; +import net.northking.cctp.se.attach.AttachInfoService; +import net.northking.cctp.se.attach.AttachmentDB; import net.northking.cctp.se.file.Attachment; import net.northking.cctp.se.util.HttpUtils; import net.northking.cctp.se.util.JsonUtils; +import net.northking.cctp.se.util.SpringUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpEntity; @@ -281,11 +284,13 @@ public class PCDeviceConnection extends AbstractDeviceConnection { log.debug("截图上传入参tenantId:{}",tenantId); log.debug("截图上传入参initData:{}", JSONObject.toJSONString(initData)); log.debug("截图入参taskId,{}", initData.get("taskId")); - Attachment upload = HttpUtils.upload(localPath, tenantId, (String)initData.get("taskId"), FileBusinessTypeEnum.PC_TASK_SCREENSHOT.getCode()); +// Attachment upload = HttpUtils.upload(localPath, tenantId, (String)initData.get("taskId"), FileBusinessTypeEnum.PC_TASK_SCREENSHOT.getCode()); + String filename = localPath.substring(localPath.lastIndexOf("\\") + 1); + AttachmentDB upload = SpringUtils.getBean(AttachInfoService.class).save(filename, localPath, tenantId, (String)initData.get("taskId"), FileBusinessTypeEnum.PC_TASK_SCREENSHOT.getCode()); if (ObjectUtil.isNull(upload) || StringUtils.isBlank(upload.getId())){ throw new RuntimeException("截图文件上传信息为空"); } - return upload.getUrlPath(); + return upload.getUrl(); }catch (Exception e){ log.error("截图上传失败", e); throw new RuntimeException(e.getMessage()); diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/repository/AttachmentInfoRepository.java b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/repository/AttachmentInfoRepository.java new file mode 100644 index 0000000..0414795 --- /dev/null +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/repository/AttachmentInfoRepository.java @@ -0,0 +1,11 @@ +package net.northking.cctp.se.repository; + +import net.northking.cctp.se.attach.AttachmentDB; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface AttachmentInfoRepository extends JpaRepository { + + +} diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/scheduler/AttachUploadScheduler.java b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/scheduler/AttachUploadScheduler.java new file mode 100644 index 0000000..79eb8a6 --- /dev/null +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/scheduler/AttachUploadScheduler.java @@ -0,0 +1,64 @@ +package net.northking.cctp.se.scheduler; + +import lombok.extern.slf4j.Slf4j; +import net.northking.cctp.se.attach.AttachInfoUpload; +import net.northking.cctp.se.attach.AttachmentDB; +import net.northking.cctp.se.config.AtuServerConfig; +import net.northking.cctp.se.repository.AttachmentInfoRepository; +import net.northking.cctp.se.thread.AttachInfoExecutorPool; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + *

Title: AttachUploadScheduler

+ *

Description: 附件信息上传检查

+ * + */ +@Component +@Slf4j +public class AttachUploadScheduler { + + @Autowired + private AtuServerConfig atuServerConfig; + + @Autowired + private AttachmentInfoRepository repo; + + @Autowired + private AttachInfoExecutorPool pool; + + /** + * 附件信息检查 + * 初始延迟时间 20秒, 3秒检测一次 + */ + @Scheduled(initialDelay = 20 * 1000, fixedDelay = 3 * 1000) + public void upload() { + try { + // 是否都空闲了 + if (!pool.isUploadAvailable()) { + return; + } + // 查询前面20条数据 + Sort orderBy = Sort.by(Sort.Order.asc("failureTimes"), Sort.Order.asc("createdTime")); + Pageable pageable = PageRequest.of(0, 10, orderBy); + Page resultPage = repo.findAll(pageable); + List content = resultPage.getContent(); + if (!content.isEmpty()) { + for (AttachmentDB db : content) { + AttachInfoUpload uploadRunnable = new AttachInfoUpload(db); + pool.uploadTaskSubmit(uploadRunnable); + } + } + // 便利 + }catch (Exception e){ + log.error("发送任务执行心跳异常", e); + } + } +} diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/script/service/ScriptRuntimeExecutor.java b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/script/service/ScriptRuntimeExecutor.java index dca5b43..bb2a3ab 100644 --- a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/script/service/ScriptRuntimeExecutor.java +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/script/service/ScriptRuntimeExecutor.java @@ -19,6 +19,8 @@ import net.northking.cctp.element.core.exception.ExecuteException; import net.northking.cctp.element.core.exception.KeywordNotFoundException; import net.northking.cctp.element.core.keyword.KeywordArgument; import net.northking.cctp.element.core.type.LibraryConstant; +import net.northking.cctp.se.attach.AttachInfoService; +import net.northking.cctp.se.attach.AttachmentDB; import net.northking.cctp.se.component.ComponentLibrary; import net.northking.cctp.se.component.ComponentManagementService; import net.northking.cctp.se.component.InternalComponent; @@ -1368,12 +1370,15 @@ public class ScriptRuntimeExecutor implements ScriptExecutor { log.debug("localPath = " + stepSnapshot); log.debug("tenantId = " + tenantId); if (StrUtil.isNotEmpty(tenantId) && StrUtil.isNotEmpty(stepSnapshot)){ - Attachment upload = HttpUtils.upload(stepSnapshot, tenantId, currentTaskId, FileBusinessTypeEnum.PC_TASK_SCREENSHOT.getCode()); +// Attachment upload = HttpUtils.upload(stepSnapshot, tenantId, currentTaskId, FileBusinessTypeEnum.PC_TASK_SCREENSHOT.getCode()); + String filename = stepSnapshot.substring(stepSnapshot.lastIndexOf("\\") + 1); + AttachmentDB upload = SpringUtils.getBean(AttachInfoService.class).save(filename, stepSnapshot, tenantId, currentTaskId, FileBusinessTypeEnum.PC_TASK_SCREENSHOT.getCode()); + if (ObjectUtil.isNull(upload) || StringUtils.isBlank(upload.getId())) { throw new RuntimeException("截图文件上传信息为空"); } log.debug("截图文件上传结果,{}", JSON.toJSONString(upload)); - stepRet.setActualImgUri(upload.getUrlPath()); + stepRet.setActualImgUri(upload.getUrl()); } } catch (Exception e) { log.error("获取步骤执行时截图失败", e); diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/thread/AttachInfoExecutorPool.java b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/thread/AttachInfoExecutorPool.java new file mode 100644 index 0000000..4540f49 --- /dev/null +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/thread/AttachInfoExecutorPool.java @@ -0,0 +1,61 @@ +package net.northking.cctp.se.thread; + +import org.springframework.stereotype.Component; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * 附件上传 + */ +public class AttachInfoExecutorPool { + + private ThreadPoolExecutor uploadPool; + + private ThreadPoolExecutor savePool; + + public AttachInfoExecutorPool() { + uploadPool = new ThreadPoolExecutor(1, 3, + 0L, TimeUnit.SECONDS, + new LinkedBlockingQueue()); + + savePool = new ThreadPoolExecutor(1, 3, + 0L, TimeUnit.SECONDS, + new LinkedBlockingQueue()); + } + + + /** + * 提交执行附件上传任务 + * @param task + */ + public void uploadTaskSubmit(Runnable task) { + uploadPool.submit(task); + } + + /** + * 线程池是否空闲 + * @return + */ + public boolean isUploadAvailable() { + return uploadPool.getActiveCount() == 0; + } + + /** + * 队列中任务剩余数量 + * @return + */ + public int uploadTaskLeft() { + return uploadPool.getQueue().size(); + } + + /** + * 提交执行附件保存任务 + * @param task + */ + public void saveTaskSubmit(Runnable task) { + savePool.submit(task); + } + +} diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/util/AttachUtils.java b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/util/AttachUtils.java new file mode 100644 index 0000000..e5abf57 --- /dev/null +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/util/AttachUtils.java @@ -0,0 +1,64 @@ +package net.northking.cctp.se.util; + +import net.northking.cctp.common.util.UUIDUtil; +import net.northking.cctp.element.core.exception.ExecuteException; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * 附件相关工具类 + */ +public class AttachUtils { + + private static final Logger logger = LoggerFactory.getLogger(AttachUtils.class); + + /** + * 生成附件id + * /yyyy/MM/dd/32位uuid[.文件后缀] + * + * @param filename 附件名称 + * @return 附件id + */ + public static String createId(String filename) { + if (StringUtils.isBlank(filename)) { + logger.error("上传资源失败:附件名称不能为空"); + throw new ExecuteException("上传资源失败:附件名称不能为空"); + } + String id; + int i = filename.lastIndexOf("."); + if (i <= 0) { // 文件没有后缀名称 + id = createDatePath() + UUIDUtil.create32UUID(); + } else { // 文件存在后缀名称 + String postfix = filename.substring(i + 1); + id = createDatePath() + UUIDUtil.create32UUID() + "." + postfix; + } + logger.debug("文件[{}] --> id: {}", filename, id); + return id; + } + + + public static String exchangeToUrl(String attachId, String tenantId) { + return String.format("%s%s", tenantId, encodeAttachId(attachId)); + } + + private static String encodeAttachId(String id) { + return id.replace("/", "_"); + } + + + /** + * 根据日期创建目录 + * + * @return 根据日期创建目录 + */ + private static String createDatePath() + { + SimpleDateFormat format = new SimpleDateFormat("/yyyy/MM/dd/"); + return format.format(new Date()); + } + +} diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/util/HttpUtils.java b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/util/HttpUtils.java index ec466f2..394ea61 100644 --- a/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/util/HttpUtils.java +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/java/net/northking/cctp/se/util/HttpUtils.java @@ -120,13 +120,17 @@ public class HttpUtils { return response.getBody(); } + public static Attachment upload(String filePath, String tenantId, String objId, String businessCode) { + return upload(filePath, tenantId, objId, businessCode, null); + } + /** * 上传资源 * @param filePath * @param tenantId * @return */ - public static Attachment upload(String filePath, String tenantId, String objId, String businessCode) { + public static Attachment upload(String filePath, String tenantId, String objId, String businessCode, String attachId) { if (StringUtils.isBlank(tenantId)) { throw new ExecuteException("上传资源失败:缺少租户信息"); } @@ -141,6 +145,9 @@ public class HttpUtils { multipartMap.add("tenantId", tenantId); multipartMap.add("objId", objId); multipartMap.add("businessCode", businessCode); + if (StringUtils.isNotBlank(attachId)) { + multipartMap.add("attachId", attachId); + } FormHttpMessageConverter converter = new FormHttpMessageConverter(); converter.addPartConverter(new ResourceHttpMessageConverter()); template.getMessageConverters().add(converter); diff --git a/cctp-atu/atu-engine/atu-script-engine/src/main/resources/application.yml b/cctp-atu/atu-engine/atu-script-engine/src/main/resources/application.yml index a32e9a9..34876b7 100644 --- a/cctp-atu/atu-engine/atu-script-engine/src/main/resources/application.yml +++ b/cctp-atu/atu-engine/atu-script-engine/src/main/resources/application.yml @@ -37,6 +37,11 @@ spring: pool: max-active: 5 max-idle: 5 + task: + scheduling: + pool: + size: 3 + thread-name-prefix: scheduler-task- management: endpoints: diff --git a/cctp-atu/atu-upper-computer/pom.xml b/cctp-atu/atu-upper-computer/pom.xml index 4bebe49..57cdb15 100644 --- a/cctp-atu/atu-upper-computer/pom.xml +++ b/cctp-atu/atu-upper-computer/pom.xml @@ -176,6 +176,14 @@ thumbnailator 0.4.8 + + com.h2database + h2 + + + org.springframework.boot + spring-boot-starter-data-jpa + \ No newline at end of file diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachInfoService.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachInfoService.java new file mode 100644 index 0000000..bfd936f --- /dev/null +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachInfoService.java @@ -0,0 +1,8 @@ +package net.northking.cctp.upperComputer.attach; + +public interface AttachInfoService { + + AttachmentDB save(String filename, String filePath, String tenantId, String objectId, String bizCode); + + AttachmentDB save(String filename, String filePath, String tenantId, int x, int y, String objectId, String bizCode); +} diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachInfoServiceImpl.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachInfoServiceImpl.java new file mode 100644 index 0000000..feff33b --- /dev/null +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachInfoServiceImpl.java @@ -0,0 +1,42 @@ +package net.northking.cctp.upperComputer.attach; + + +import net.northking.cctp.upperComputer.utils.AttachUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; + +@Service +public class AttachInfoServiceImpl implements AttachInfoService { + + private static final Logger logger = LoggerFactory.getLogger(AttachInfoServiceImpl.class); + + @Autowired + private AttachmentInfoRepository attachRepo; + + @Override + public AttachmentDB save(String filename, String filePath, String tenantId, String objectId, String bizCode) { + return save(filename, filePath, tenantId, -1, -1, objectId, bizCode); + } + + @Override + public AttachmentDB save(String filename, String filePath, String tenantId, int x, int y, String objectId, String bizCode) { + AttachmentDB attachmentDB = new AttachmentDB(); + attachmentDB.setId(AttachUtils.createId(filename)); + attachmentDB.setUrl(AttachUtils.exchangeToUrl(attachmentDB.getId(), tenantId)); + attachmentDB.setFilename(filename); + attachmentDB.setFilePath(filePath); + attachmentDB.setCreatedTime(new Date()); + attachmentDB.setTenantId(tenantId); + attachmentDB.setFailureTimes(0); + attachmentDB.setX(x); + attachmentDB.setY(y); + attachmentDB.setObjectId(objectId); + attachmentDB.setBizCode(bizCode); + attachRepo.saveAndFlush(attachmentDB); + return attachmentDB; + } +} diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachInfoUpload.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachInfoUpload.java new file mode 100644 index 0000000..4a4fb00 --- /dev/null +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachInfoUpload.java @@ -0,0 +1,99 @@ +package net.northking.cctp.upperComputer.attach; + +import cn.hutool.core.bean.BeanUtil; +import net.northking.cctp.upperComputer.entity.Attachment; +import net.northking.cctp.upperComputer.entity.DebuggerDeviceInfo; +import net.northking.cctp.upperComputer.utils.HttpUtils; +import net.northking.cctp.upperComputer.utils.SpringUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +/** + * 附件信息上传 + * + */ +public class AttachInfoUpload implements Runnable { + + private static final Logger logger = LoggerFactory.getLogger(AttachInfoUpload.class); + + private AttachmentDB attachmentDB; + + public AttachInfoUpload(AttachmentDB attachmentDB) { + this.attachmentDB = attachmentDB; + } + + @Override + public void run() { + AttachmentInfoRepository repo = SpringUtils.getBean(AttachmentInfoRepository.class); + try { + String filePath = attachmentDB.getFilePath(); + if (attachmentDB.getX() > 0 && attachmentDB.getY() > 0) { + filePath = addSignatureToImage(attachmentDB.getFilePath(), attachmentDB.getX(), attachmentDB.getY()); + } + String serverAddr = SpringUtils.getProperties("nk.mobile-computer.serverAddr"); + String publicUploadAddr = SpringUtils.getProperties("nk.mobile-computer.publicUploadAddr"); + String uploadUrl = serverAddr + publicUploadAddr; + Attachment upload = HttpUtils.upload(uploadUrl, + filePath, attachmentDB.getTenantId(), + attachmentDB.getObjectId(), attachmentDB.getBizCode(), + attachmentDB.getId()); + if (upload != null && StringUtils.isNotBlank(upload.getUrlPath())) { + // 上传成功 + logger.debug("文件上传成功:{}, storagePath -> {}", BeanUtil.beanToMap(upload).toString(), attachmentDB.getId()); + // 删除数据库信息 + repo.deleteById(attachmentDB.getId()); + } + } catch (Exception e) { + logger.error("附件上传失败", e); + // 附件信息的失败次数加1,并更新数据库数据 + attachmentDB.setFailureTimes(attachmentDB.getFailureTimes() + 1); + repo.saveAndFlush(attachmentDB); + } + + } + + /** + * 给截图增加红点操作。 + * @param filePath + * @param x + * @param y + * @return + */ + private String addSignatureToImage(String filePath, Integer x, Integer y) { + if (x == null || y == null) { + return filePath; + } + File originFile = new File(filePath); + if (!originFile.exists()) { + logger.info("截图文件不存在:{}", originFile.getAbsolutePath()); + return filePath; + } + String fullName = originFile.getName(); + String suffix = fullName.substring(fullName.lastIndexOf(".") + 1); + String name = fullName.substring(0, fullName.lastIndexOf(".")); + File targetFile = new File(originFile.getParentFile().getAbsolutePath() + File.separator + name + "_with_dot" + "." + suffix); + try { + BufferedImage bi = ImageIO.read(originFile); + Graphics2D g2d = bi.createGraphics(); // 生成画布 + g2d.setColor(Color.RED); // 红色 + g2d.fillOval(x, y, 20, 20); // 在图片的x,y上画上一个直径20的实心原点 + g2d.dispose(); + ImageIO.write(bi, suffix, targetFile); + } catch (IOException e) { + logger.error("io异常", e); + } catch (Exception e) { + logger.error("添加红点失败", e); + } + if (!targetFile.exists()) { + targetFile = originFile; + } + return targetFile.getAbsolutePath(); + } +} diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachmentDB.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachmentDB.java new file mode 100644 index 0000000..1f78c8e --- /dev/null +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachmentDB.java @@ -0,0 +1,155 @@ +package net.northking.cctp.upperComputer.attach; + +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.Date; + +/** + * 附件对象 + */ +@Table(name = "attachment_info") +public class AttachmentDB { + + @Id + private String id; + + private String url; + + private String filename; + + private String filePath; + + /** + * 创建时间 + */ + private Date createdTime; + + /** + * 红点x坐标 + */ + private int x; + + /** + * 红点y坐标 + */ + private int y; + + /** + * 租户id + */ + private String tenantId; + + /** + * 上传失败次数 + */ + private int failureTimes; + + private String objectId; + + private String bizCode; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getFilename() { + return filename; + } + + public void setFilename(String filename) { + this.filename = filename; + } + + public String getFilePath() { + return filePath; + } + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public Date getCreatedTime() { + return createdTime; + } + + public void setCreatedTime(Date createdTime) { + this.createdTime = createdTime; + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + + public int getFailureTimes() { + return failureTimes; + } + + public void setFailureTimes(int failureTimes) { + this.failureTimes = failureTimes; + } + + public String getObjectId() { + return objectId; + } + + public void setObjectId(String objectId) { + this.objectId = objectId; + } + + public String getBizCode() { + return bizCode; + } + + public void setBizCode(String bizCode) { + this.bizCode = bizCode; + } + + @Override + public String toString() { + return "AttachmentDB{" + + "id='" + id + '\'' + + ", url='" + url + '\'' + + ", filename='" + filename + '\'' + + ", filePath='" + filePath + '\'' + + ", createdTime=" + createdTime + + ", x=" + x + + ", y=" + y + + ", tenantId='" + tenantId + '\'' + + ", failureTimes=" + failureTimes + + ", objectId='" + objectId + '\'' + + ", bizCode='" + bizCode + '\'' + + '}'; + } +} diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachmentInfoRepository.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachmentInfoRepository.java new file mode 100644 index 0000000..f8527c8 --- /dev/null +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/attach/AttachmentInfoRepository.java @@ -0,0 +1,10 @@ +package net.northking.cctp.upperComputer.attach; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface AttachmentInfoRepository extends JpaRepository { + + +} diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/config/ExecutorPoolConfig.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/config/ExecutorPoolConfig.java new file mode 100644 index 0000000..452c684 --- /dev/null +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/config/ExecutorPoolConfig.java @@ -0,0 +1,21 @@ +package net.northking.cctp.upperComputer.config; + +import net.northking.cctp.upperComputer.thread.AttachInfoExecutorPool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ExecutorPoolConfig { + + private static final Logger logger = LoggerFactory.getLogger(ExecutorPoolConfig.class); + + + @Bean + public AttachInfoExecutorPool createAttachInfoPool() { + AttachInfoExecutorPool pool = new AttachInfoExecutorPool(); + return pool; + } + +} diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/service/AndroidDebuggerServiceImpl.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/service/AndroidDebuggerServiceImpl.java index b706784..ca88deb 100644 --- a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/service/AndroidDebuggerServiceImpl.java +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/service/AndroidDebuggerServiceImpl.java @@ -7,6 +7,8 @@ import com.alibaba.fastjson.JSONObject; import io.appium.java_client.AppiumDriver; import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.ios.IOSDriver; +import net.northking.cctp.upperComputer.attach.AttachInfoService; +import net.northking.cctp.upperComputer.attach.AttachmentDB; import net.northking.cctp.upperComputer.config.MobileProperty; import net.northking.cctp.upperComputer.deviceManager.screen.AndroidScreenResponseThread; import net.northking.cctp.upperComputer.deviceManager.thread.AndroidDeviceInitThread; @@ -40,10 +42,14 @@ import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import javax.annotation.PostConstruct; +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.util.*; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import static io.appium.java_client.remote.AndroidMobileCapabilityType.RESET_KEYBOARD; @@ -70,6 +76,9 @@ public class AndroidDebuggerServiceImpl extends AbstractDebuggerService { private Adb adb; + @Autowired + private AttachInfoService attachInfoService; + @Value("${appium.server.host:127.0.0.1}") private String appiumHost; @@ -731,11 +740,13 @@ public class AndroidDebuggerServiceImpl extends AbstractDebuggerService { String tenantId = info.getTenantId(); logger.debug("开始上传截图,任务信息:{}",JSON.toJSONString(info)); String taskId = info.getTaskId(); - Attachment upload = HttpUtils.upload(mobileProperty.getServerAddr() + mobileProperty.getPublicUploadAddr(), file.getAbsolutePath(), tenantId, taskId, FileBusinessTypeEnum.MOBILE_TASK_SCREENSHOT.getCode()); +// Attachment upload = HttpUtils.upload(mobileProperty.getServerAddr() + mobileProperty.getPublicUploadAddr(), file.getAbsolutePath(), tenantId, taskId, FileBusinessTypeEnum.MOBILE_TASK_SCREENSHOT.getCode()); + // todo: 把截图信息保存到数据库待处理 + AttachmentDB upload = attachInfoService.save(file.getName(), file.getAbsolutePath(), tenantId, info.getX(), info.getY(), taskId, FileBusinessTypeEnum.MOBILE_TASK_SCREENSHOT.getCode()); if (null != upload && StringUtils.isNotBlank(upload.getId())) { logger.debug("文件上传成功,返回id:{}", upload.getId()); - path = upload.getUrlPath(); + path = upload.getUrl(); } } catch (ExecuteException e) { logger.error("上传截图失败", e); diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/service/IosDebuggerServiceImpl.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/service/IosDebuggerServiceImpl.java index 5e92e5a..f33d688 100644 --- a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/service/IosDebuggerServiceImpl.java +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/service/IosDebuggerServiceImpl.java @@ -4,6 +4,8 @@ import cn.hutool.core.codec.Base64; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import io.appium.java_client.AppiumDriver; +import net.northking.cctp.upperComputer.attach.AttachInfoService; +import net.northking.cctp.upperComputer.attach.AttachmentDB; import net.northking.cctp.upperComputer.config.MobileProperty; import net.northking.cctp.upperComputer.deviceManager.common.PyMobileDevice; import net.northking.cctp.upperComputer.deviceManager.screen.IosScreenResponseThread; @@ -58,6 +60,9 @@ public class IosDebuggerServiceImpl extends AbstractDebuggerService { super.setMobileProperty(mobileProperty); } + @Autowired + private AttachInfoService attachInfoService; + @Override public Object getUiTree(String deviceId) { PhoneEntity phoneEntity = IOSDeviceManager.getInstance().getPhoneEntity(deviceId); @@ -194,17 +199,19 @@ public class IosDebuggerServiceImpl extends AbstractDebuggerService { @Override public String uploadShotAllScreen(DebuggerDeviceInfo info) { - File file = ScreenShotUtils.getIOSMobileScreenShot(info.getDeviceId()); + File file = deviceHandleHelper.getScreenShotFile(info.getDeviceId()); String path = null; try { //租户id String tenantId = info.getTenantId(); String taskId = info.getTaskId(); logger.debug("开始上传截图,任务信息:{}",JSON.toJSONString(info)); - Attachment upload = HttpUtils.upload(mobileProperty.getServerAddr() + mobileProperty.getPublicUploadAddr(), file.getAbsolutePath(), tenantId, taskId, FileBusinessTypeEnum.MOBILE_TASK_SCREENSHOT.getCode()); +// Attachment upload = HttpUtils.upload(mobileProperty.getServerAddr() + mobileProperty.getPublicUploadAddr(), file.getAbsolutePath(), tenantId, taskId, FileBusinessTypeEnum.MOBILE_TASK_SCREENSHOT.getCode()); + // todo: 把截图信息保存到数据库待处理 + AttachmentDB upload = attachInfoService.save(file.getName(), file.getAbsolutePath(), tenantId, info.getX(), info.getY(), taskId, FileBusinessTypeEnum.MOBILE_TASK_SCREENSHOT.getCode()); if (null != upload && org.apache.commons.lang3.StringUtils.isNotBlank(upload.getId())) { logger.debug("文件上传成功,返回id:{}", upload.getId()); - path = upload.getUrlPath(); + path = upload.getUrl(); } } catch (ExecuteException e) { logger.error("截图失败",e); diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/thread/AttachInfoExecutorPool.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/thread/AttachInfoExecutorPool.java new file mode 100644 index 0000000..819c695 --- /dev/null +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/thread/AttachInfoExecutorPool.java @@ -0,0 +1,59 @@ +package net.northking.cctp.upperComputer.thread; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * 附件上传 + */ +public class AttachInfoExecutorPool { + + private ThreadPoolExecutor uploadPool; + + private ThreadPoolExecutor savePool; + + public AttachInfoExecutorPool() { + uploadPool = new ThreadPoolExecutor(1, 3, + 0L, TimeUnit.SECONDS, + new LinkedBlockingQueue()); + + savePool = new ThreadPoolExecutor(1, 3, + 0L, TimeUnit.SECONDS, + new LinkedBlockingQueue()); + } + + + /** + * 提交执行附件上传任务 + * @param task + */ + public void uploadTaskSubmit(Runnable task) { + uploadPool.submit(task); + } + + /** + * 线程池是否空闲 + * @return + */ + public boolean isUploadAvailable() { + return uploadPool.getActiveCount() == 0; + } + + /** + * 队列中任务剩余数量 + * @return + */ + public int uploadTaskLeft() { + return uploadPool.getQueue().size(); + } + + /** + * 提交执行附件保存任务 + * @param task + */ + public void saveTaskSubmit(Runnable task) { + savePool.submit(task); + } + +} diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/utils/AttachUtils.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/utils/AttachUtils.java new file mode 100644 index 0000000..f390f84 --- /dev/null +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/utils/AttachUtils.java @@ -0,0 +1,64 @@ +package net.northking.cctp.upperComputer.utils; + +import net.northking.cctp.upperComputer.exception.ParamMistakeException; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.UUID; + +/** + * 附件相关工具类 + */ +public class AttachUtils { + + private static final Logger logger = LoggerFactory.getLogger(AttachUtils.class); + + /** + * 生成附件id + * /yyyy/MM/dd/32位uuid[.文件后缀] + * + * @param filename 附件名称 + * @return 附件id + */ + public static String createId(String filename) { + if (StringUtils.isBlank(filename)) { + logger.error("上传资源失败:附件名称不能为空"); + throw new ParamMistakeException("上传资源失败:附件名称不能为空"); + } + String id; + int i = filename.lastIndexOf("."); + if (i <= 0) { // 文件没有后缀名称 + id = createDatePath() + UUID.randomUUID().toString().replace("-",""); + } else { // 文件存在后缀名称 + String postfix = filename.substring(i + 1); + id = createDatePath() + UUID.randomUUID().toString().replace("-","") + "." + postfix; + } + logger.debug("文件[{}] --> id: {}", filename, id); + return id; + } + + + public static String exchangeToUrl(String attachId, String tenantId) { + return String.format("%s%s", tenantId, encodeAttachId(attachId)); + } + + private static String encodeAttachId(String id) { + return id.replace("/", "_"); + } + + + /** + * 根据日期创建目录 + * + * @return 根据日期创建目录 + */ + private static String createDatePath() + { + SimpleDateFormat format = new SimpleDateFormat("/yyyy/MM/dd/"); + return format.format(new Date()); + } + +} diff --git a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/utils/HttpUtils.java b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/utils/HttpUtils.java index e994faf..c067718 100644 --- a/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/utils/HttpUtils.java +++ b/cctp-atu/atu-upper-computer/src/main/java/net/northking/cctp/upperComputer/utils/HttpUtils.java @@ -311,6 +311,7 @@ public class HttpUtils { } return result; } + /** * 上传资源 * @param filePath @@ -318,6 +319,16 @@ public class HttpUtils { * @return */ public static Attachment upload(String url, String filePath, String tenantId, String objId, String businessCode) { + return upload(url, filePath, tenantId, objId, businessCode, null); + } + + /** + * 上传资源 + * @param filePath + * @param tenantId + * @return + */ + public static Attachment upload(String url, String filePath, String tenantId, String objId, String businessCode, String attachId) { if (StringUtils.isBlank(tenantId)) { throw new ExecuteException("上传资源失败:缺少租户信息"); } @@ -330,6 +341,9 @@ public class HttpUtils { multipartMap.add("tenantId", tenantId); multipartMap.add("objId", objId); multipartMap.add("businessCode", businessCode); + if (StringUtils.isNotBlank(attachId)) { + multipartMap.add("attachId", attachId); + } FormHttpMessageConverter converter = new FormHttpMessageConverter(); converter.addPartConverter(new ResourceHttpMessageConverter()); template.getMessageConverters().add(converter); diff --git a/cctp-atu/atu-upper-computer/src/main/resources/application.yml b/cctp-atu/atu-upper-computer/src/main/resources/application.yml index 424cdb3..0dc1a2e 100644 --- a/cctp-atu/atu-upper-computer/src/main/resources/application.yml +++ b/cctp-atu/atu-upper-computer/src/main/resources/application.yml @@ -14,6 +14,29 @@ spring: jackson: serialization: write-dates-as-timestamps: true + jpa: + show-sql: false + hibernate: + ddl-auto: update + database: h2 + open-in-view: false + datasource: + url: jdbc:h2:file:./.h2/db + username: engine + password: 123456 + driver-class-name: org.h2.Driver + h2: + console: + path: /h2 + enabled: true + settings: + trace: false + web-allow-others: true + task: + scheduling: + pool: + size: 3 + thread-name-prefix: scheduler-task- nk: mobile-computer: password: 123456 diff --git a/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/S3File.java b/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/S3File.java index da60de7..2baf06a 100644 --- a/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/S3File.java +++ b/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/S3File.java @@ -19,6 +19,7 @@ public class S3File implements NKFile private String tenantId; private String objId; private String businessCode; + private String storagePath; public S3File() { @@ -47,6 +48,33 @@ public class S3File implements NKFile } } + public S3File(String bucket, String tenantId, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode, String attachId) { + this.bucket = bucket; + this.tenantId = tenantId; + this.contentType = multipartFile.getContentType(); + this.length = multipartFile.getSize(); + this.fileName = multipartFile.getOriginalFilename(); + this.objId = objId; + this.businessCode = businessCode.getCode(); + assert fileName != null; + int index = fileName.lastIndexOf("."); + if (null != attachId && attachId.length() > 0) { + this.id = attachId; + this.storagePath = attachId; + } else { + if (index <= 0) { + // 文件没有后缀名 + this.id = createDatePath() + UUIDUtil.create32UUID(); + this.storagePath = this.id; + } else { + String postfix = fileName.substring(index + 1); + // 文件ID长度= 32 + 11 + 32 + 后缀名(<10) + this.id = createDatePath() + UUIDUtil.create32UUID() + "." + postfix; + this.storagePath = this.id; + } + } + } + public S3File(String bucket, String tenantId, String suffixName) { this.bucket = bucket; @@ -209,4 +237,12 @@ public class S3File implements NKFile public void setBusinessCode(String businessCode) { this.businessCode = businessCode; } + + public String getStoragePath() { + return storagePath; + } + + public void setStoragePath(String storagePath) { + this.storagePath = storagePath; + } } diff --git a/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/SimpleStorageService.java b/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/SimpleStorageService.java index 1fad023..8540fa5 100644 --- a/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/SimpleStorageService.java +++ b/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/SimpleStorageService.java @@ -24,6 +24,18 @@ public interface SimpleStorageService * @throws FileUploadException 异常 */ NKFile upload(String tenant, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode) throws FileUploadException, IOException; + /** + * 上传文件 + * + * @param tenant 租户 + * @param multipartFile 文件 + * @param objId 关联对象Id + * @param businessCode 文件业务类型枚举 + * @param attachId 文件id + * @return 文件记录 + * @throws FileUploadException 异常 + */ + NKFile upload(String tenant, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode, String attachId) throws FileUploadException, IOException; /** * 文件分片上传 diff --git a/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/impl/MinioFileStorage.java b/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/impl/MinioFileStorage.java index 8755caf..48e8302 100644 --- a/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/impl/MinioFileStorage.java +++ b/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/impl/MinioFileStorage.java @@ -73,6 +73,29 @@ public class MinioFileStorage implements SimpleStorageService { return s3File; } + /** + * 上传文件 + * + * @param tenant 租户 + * @param multipartFile 文件 + * @param objId 关联对象Id + * @param businessCode 文件业务类型枚举 + * @param attachId 文件id + * @return 文件记录 + * @throws FileUploadException 异常 + */ + @Override + public NKFile upload(String tenant, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode, String attachId) throws FileUploadException, IOException { + S3File s3File = new S3File(properties.getBucket(), tenant, multipartFile, objId, businessCode, attachId); + putObject(s3File, multipartFile.getInputStream()); + + if (properties.isUseMsgQueue() && attachmentProducer != null) + { + attachmentProducer.process(s3File); + } + return s3File; + } + public NKFile uploadChunk(String tenantId, MultipartFile multipartFile, String uploadId, String chunkIndex) throws FileUploadException, IOException { S3File s3File = new S3File(properties.getBucket(), tenantId, multipartFile, uploadId, chunkIndex); diff --git a/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/impl/SeaweedFileStorage.java b/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/impl/SeaweedFileStorage.java index 29b8d07..83cd56d 100644 --- a/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/impl/SeaweedFileStorage.java +++ b/cloud-basic/cctp-commons/src/main/java/net/northking/cctp/common/s3/impl/SeaweedFileStorage.java @@ -74,6 +74,30 @@ public class SeaweedFileStorage implements SimpleStorageService { return s3File; } + /** + * 上传文件 + * + * @param tenant 租户 + * @param multipartFile 文件 + * @param objId 关联对象Id + * @param businessCode 文件业务类型枚举 + * @param attachId 文件id + * @return 文件记录 + * @throws FileUploadException 异常 + */ + @Override + public NKFile upload(String tenant, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode, String attachId) throws FileUploadException, IOException { + logger.debug("配置动态刷新:AmazonS3Properties:{}", JSON.toJSONString(properties)); + S3File s3File = new S3File(properties.getBucket(), tenant, multipartFile, objId, businessCode, attachId); + putObject(s3File, multipartFile.getInputStream()); + + if (properties.isUseMsgQueue() && attachmentProducer != null) + { + attachmentProducer.process(s3File); + } + return s3File; + } + public NKFile uploadChunk(String tenantId, MultipartFile multipartFile, String uploadId, String chunkIndex) throws FileUploadException, IOException { logger.debug("tenantId:{},uploadId:{},chunkIndex:{},fileName:{},size:{}",tenantId, uploadId, chunkIndex, multipartFile.getOriginalFilename(), multipartFile.getSize()); diff --git a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/api/AttachFileCtrl.java b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/api/AttachFileCtrl.java index 2235158..e5e6075 100644 --- a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/api/AttachFileCtrl.java +++ b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/api/AttachFileCtrl.java @@ -164,7 +164,8 @@ public class AttachFileCtrl @RequestParam("file") MultipartFile multipartFile, @RequestParam("tenantId") String tenantId, @RequestParam(value = "objId", required = false) String objId, - @RequestParam("businessCode") String businessCode) { + @RequestParam("businessCode") String businessCode, + @RequestParam(value = "attachId", required = false) String attachId) { ResultWrapper> wrapper = new ResultWrapper<>(); FileBusinessTypeEnum fileBusinessTypeByCode = FileBusinessTypeEnum.getFileBusinessTypeByCode(businessCode); if (null == fileBusinessTypeByCode) { @@ -176,7 +177,7 @@ public class AttachFileCtrl return wrapper; } NKSecurityContext.setTenantId(tenantId); - return attachFileService.uploadResource(response, multipartFile, objId, fileBusinessTypeByCode); + return attachFileService.uploadResource(response, multipartFile, objId, fileBusinessTypeByCode, attachId); } @PostMapping(value = {"/v1/uploadForApp"}, diff --git a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/api/service/AttachFileService.java b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/api/service/AttachFileService.java index 2851a67..90ec578 100644 --- a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/api/service/AttachFileService.java +++ b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/api/service/AttachFileService.java @@ -68,7 +68,7 @@ public interface AttachFileService ResultWrapper mergeChunkFiles(ChunkFiles chunkFiles); - ResultWrapper> uploadResource(HttpServletResponse response, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode); + ResultWrapper> uploadResource(HttpServletResponse response, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode, String attachId); ResultWrapper update(Map file); diff --git a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/api/service/AttachFileServiceImpl.java b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/api/service/AttachFileServiceImpl.java index 732b23f..df4059a 100644 --- a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/api/service/AttachFileServiceImpl.java +++ b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/api/service/AttachFileServiceImpl.java @@ -104,8 +104,15 @@ public class AttachFileServiceImpl implements AttachFileService response.setStatus(HttpStatus.NOT_FOUND.value()); return; } - - Attachment attachment = attachmentService.findByPK(tenantId, objectId); + String id = objectId; + // 判断objectId是id还是storagePath,如果是id,那么只有一个/ + if (objectId.lastIndexOf("/") > 0) { + Attachment attachment = attachmentService.queryByStoragePath(tenantId, objectId); // 通过storagePath查询附件的id + if (attachment != null) { + id = attachment.getId(); + } + } + Attachment attachment = attachmentService.findByPK(tenantId, id); boolean check = false; int i=0; while (i<10){ @@ -115,7 +122,7 @@ public class AttachFileServiceImpl implements AttachFileService } catch (Exception e) { logger.error("等待报错",e); } - attachment = attachmentService.findByPK(tenantId, objectId); + attachment = attachmentService.findByPK(tenantId, id); }else{ check=true; break; @@ -194,7 +201,7 @@ public class AttachFileServiceImpl implements AttachFileService } @Override - public ResultWrapper> uploadResource(HttpServletResponse response, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode) + public ResultWrapper> uploadResource(HttpServletResponse response, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode, String attachId) { ResultWrapper> resultWrapper = new ResultWrapper<>(); resultWrapper.setData(new HashMap<>()); @@ -202,7 +209,7 @@ public class AttachFileServiceImpl implements AttachFileService String userId = NKSecurityContext.getUserId(); try { - NKFile nkFile = storageService.upload(tenantId, multipartFile, objId, businessCode); + NKFile nkFile = storageService.upload(tenantId, multipartFile, objId, businessCode, attachId); Attachment attachment = new Attachment(); BeanUtils.copyProperties(nkFile, attachment); @@ -211,6 +218,7 @@ public class AttachFileServiceImpl implements AttachFileService attachment.setObjId(objId); attachment.setBusinessCode(businessCode.getCode()); attachment.setOverTime(businessCode.getOverTime()); + attachment.setStoragePath(attachId); attachmentService.insert(attachment); String urlPath = tenantId + encodeFileId(nkFile.getId()); diff --git a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/dao/AttachmentDao.java b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/dao/AttachmentDao.java index 76e38af..87fdfd1 100644 --- a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/dao/AttachmentDao.java +++ b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/dao/AttachmentDao.java @@ -50,4 +50,6 @@ public interface AttachmentDao extends AttachmentMapper { List queryByOverTime(@Param("overTime") LocalDateTime overTime, @Param("tableSuffix") String tableSuffix); List queryByBusiness(@Param("date") LocalDate date, @Param("tableSuffix") String tableSuffix); + + Attachment queryByStoragePath(Attachment attachment); } diff --git a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/entity/Attachment.java b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/entity/Attachment.java index 1af9acf..df6982c 100644 --- a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/entity/Attachment.java +++ b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/entity/Attachment.java @@ -39,6 +39,10 @@ public class Attachment extends TenantPartition implements NKFile, POJO * 关联对象 */ private String objId; + /** + * 关联对象 + */ + private String storagePath; /** * 文件业务类型 */ @@ -219,4 +223,12 @@ public class Attachment extends TenantPartition implements NKFile, POJO public void setOverTime(Date overTime) { this.overTime = overTime; } + + public String getStoragePath() { + return storagePath; + } + + public void setStoragePath(String storagePath) { + this.storagePath = storagePath; + } } diff --git a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/impl/AttachmentServiceImpl.java b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/impl/AttachmentServiceImpl.java index 31fe10e..51b3df1 100644 --- a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/impl/AttachmentServiceImpl.java +++ b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/impl/AttachmentServiceImpl.java @@ -173,5 +173,15 @@ public class AttachmentServiceImpl extends TenantPaginationService i return attachmentDao.findByPK(attachment); } + @Override + public Attachment queryByStoragePath(String tenantId, String storagePath) + { + Attachment attachment = new Attachment(); + attachment.setTenantId(tenantId); + attachment.setStoragePath(storagePath); + return attachmentDao.queryByStoragePath(attachment); + } + + } diff --git a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/service/AttachmentService.java b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/service/AttachmentService.java index eb8f3d2..a92f18c 100644 --- a/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/service/AttachmentService.java +++ b/cloud-platform/cctp-attachment/src/main/java/net/northking/cctp/attachment/db/service/AttachmentService.java @@ -86,4 +86,6 @@ public interface AttachmentService extends BasicService List queryByOverTime(LocalDateTime now); List queryByBusiness(LocalDate now); + + Attachment queryByStoragePath(String tenantId, String storagePath); } diff --git a/cloud-platform/cctp-attachment/src/main/resources/mybatis/base/Attachment.Mapper.xml b/cloud-platform/cctp-attachment/src/main/resources/mybatis/base/Attachment.Mapper.xml index 39610a7..e085459 100644 --- a/cloud-platform/cctp-attachment/src/main/resources/mybatis/base/Attachment.Mapper.xml +++ b/cloud-platform/cctp-attachment/src/main/resources/mybatis/base/Attachment.Mapper.xml @@ -17,6 +17,8 @@ + + @@ -41,6 +43,7 @@ ,content_type ,length ,obj_id + ,storage_path ,business_code ,over_time ,created_by @@ -112,6 +115,9 @@ AND obj_id=#{objId,jdbcType=VARCHAR} + + + AND storage_path=#{storage_path,jdbcType=VARCHAR} AND business_code=#{businessCode,jdbcType=VARCHAR} @@ -156,6 +162,9 @@ obj_id, + + storage_path, + business_code, @@ -197,6 +206,9 @@ #{objId,jdbcType=VARCHAR}, + + #{storagePath,jdbcType=VARCHAR}, + #{businessCode,jdbcType=VARCHAR}, @@ -233,6 +245,7 @@ content_type, length, obj_id, + storage_path, business_code, over_time, created_by, @@ -250,6 +263,7 @@ #{item.contentType, jdbcType=VARCHAR}, #{item.length, jdbcType=BIGINT}, #{item.objId, jdbcType=VARCHAR}, + #{item.storagePath, jdbcType=VARCHAR}, #{item.businessCode, jdbcType=VARCHAR}, #{item.overTime, jdbcType=TIMESTAMP}, #{item.createdBy, jdbcType=VARCHAR}, @@ -278,6 +292,9 @@ obj_id = #{objId, jdbcType=VARCHAR}, + + storage_path = #{storagePath, jdbcType=VARCHAR}, + business_code = #{businessCode, jdbcType=VARCHAR}, @@ -327,6 +344,9 @@ AND obj_id = #{objId,jdbcType=VARCHAR} + + AND storage_path = #{storagePath,jdbcType=VARCHAR} + AND business_code = #{businessCode,jdbcType=VARCHAR} @@ -370,6 +390,9 @@ AND obj_id=#{objId,jdbcType=VARCHAR} + + AND storage_path=#{storagePath,jdbcType=VARCHAR} + AND business_code=#{businessCode,jdbcType=VARCHAR} diff --git a/cloud-platform/cctp-attachment/src/main/resources/mybatis/ext/Attachment.Dao.xml b/cloud-platform/cctp-attachment/src/main/resources/mybatis/ext/Attachment.Dao.xml index c06e363..98112ab 100644 --- a/cloud-platform/cctp-attachment/src/main/resources/mybatis/ext/Attachment.Dao.xml +++ b/cloud-platform/cctp-attachment/src/main/resources/mybatis/ext/Attachment.Dao.xml @@ -39,6 +39,7 @@ length BIGINT comment '文件长度', business_code varchar(50) DEFAULT NULL, obj_id varchar(50) DEFAULT NULL COMMENT '关联对象Id', + storage_path varchar(128) DEFAULT NULL COMMENT '存储路径', over_time DATETIME DEFAULT NULL, created_by VARCHAR(32) COMMENT '创建人' , created_time DATETIME COMMENT '创建时间' , @@ -183,4 +184,13 @@ ) limit 5000 + \ No newline at end of file