执行任务的步骤截图,异步上传优化

1.文件服务的数据库cctp_attachment的表增加字段:存储路径storage_path,长度128位
2.cctp-commons关于的文件上传增加支持外部传入指定id的逻辑
3.由于使用了seaweedfs,上传完成后会使用volume id和file key重新作为附件的id存入到数据,所以增加了storage_path保存外部传入id
4.在下载附件的逻辑的增加判断,如果分割后的字符串存在多个/那么使用storagePath查询附件id再下载
5.执行引擎的修改是对pc的截图异步上传。
6.上位机的修改是ios和安卓的截图异步上传。
7.大致逻辑:步骤截图后,将文件名、文件路径、任务id、xy坐标、租户id、业务代码存入到本地h2数据库;通过定时任务,如果线程池是空闲,那么每次查询前20条数据,使用线程池进行遍历上传。
master
李杰应 2024-10-25 04:40:53 +08:00
parent c053ed2583
commit 8666c2cf92
39 changed files with 1092 additions and 18 deletions

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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() {
// 根据信息添加红点或者其他标记
}
}

View File

@ -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;
}

View File

@ -2,6 +2,7 @@ package net.northking.cctp.se.config;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import lombok.Data; import lombok.Data;
import net.northking.cctp.se.thread.AttachInfoExecutorPool;
import net.northking.cctp.se.thread.ExecutorPool; import net.northking.cctp.se.thread.ExecutorPool;
import net.northking.cctp.se.util.SpringUtils; import net.northking.cctp.se.util.SpringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -26,6 +27,11 @@ public class ExecutorPoolConfig {
return executorPool; return executorPool;
} }
@Bean
public AttachInfoExecutorPool createAttachInfoPool() {
AttachInfoExecutorPool pool = new AttachInfoExecutorPool();
return pool;
}
@ConfigurationProperties(prefix = "atu.engine.executor-pool") @ConfigurationProperties(prefix = "atu.engine.executor-pool")
@Configuration @Configuration

View File

@ -13,9 +13,12 @@ import net.northking.cctp.common.http.ResultWrapper;
import net.northking.cctp.element.core.exception.ExecuteException; import net.northking.cctp.element.core.exception.ExecuteException;
import net.northking.cctp.pc.driver.dto.EngineResultDto; import net.northking.cctp.pc.driver.dto.EngineResultDto;
import net.northking.cctp.pc.driver.socket.PCDriver; 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.file.Attachment;
import net.northking.cctp.se.util.HttpUtils; import net.northking.cctp.se.util.HttpUtils;
import net.northking.cctp.se.util.JsonUtils; import net.northking.cctp.se.util.JsonUtils;
import net.northking.cctp.se.util.SpringUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
@ -281,11 +284,13 @@ public class PCDeviceConnection extends AbstractDeviceConnection {
log.debug("截图上传入参tenantId{}",tenantId); log.debug("截图上传入参tenantId{}",tenantId);
log.debug("截图上传入参initData{}", JSONObject.toJSONString(initData)); log.debug("截图上传入参initData{}", JSONObject.toJSONString(initData));
log.debug("截图入参taskId,{}", initData.get("taskId")); 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())){ if (ObjectUtil.isNull(upload) || StringUtils.isBlank(upload.getId())){
throw new RuntimeException("截图文件上传信息为空"); throw new RuntimeException("截图文件上传信息为空");
} }
return upload.getUrlPath(); return upload.getUrl();
}catch (Exception e){ }catch (Exception e){
log.error("截图上传失败", e); log.error("截图上传失败", e);
throw new RuntimeException(e.getMessage()); throw new RuntimeException(e.getMessage());

View File

@ -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<AttachmentDB, String> {
}

View File

@ -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;
/**
* <p>Title: AttachUploadScheduler</p>
* <p>Description: </p>
*
*/
@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<AttachmentDB> resultPage = repo.findAll(pageable);
List<AttachmentDB> content = resultPage.getContent();
if (!content.isEmpty()) {
for (AttachmentDB db : content) {
AttachInfoUpload uploadRunnable = new AttachInfoUpload(db);
pool.uploadTaskSubmit(uploadRunnable);
}
}
// 便利
}catch (Exception e){
log.error("发送任务执行心跳异常", e);
}
}
}

View File

@ -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.exception.KeywordNotFoundException;
import net.northking.cctp.element.core.keyword.KeywordArgument; import net.northking.cctp.element.core.keyword.KeywordArgument;
import net.northking.cctp.element.core.type.LibraryConstant; 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.ComponentLibrary;
import net.northking.cctp.se.component.ComponentManagementService; import net.northking.cctp.se.component.ComponentManagementService;
import net.northking.cctp.se.component.InternalComponent; import net.northking.cctp.se.component.InternalComponent;
@ -1368,12 +1370,15 @@ public class ScriptRuntimeExecutor implements ScriptExecutor {
log.debug("localPath = " + stepSnapshot); log.debug("localPath = " + stepSnapshot);
log.debug("tenantId = " + tenantId); log.debug("tenantId = " + tenantId);
if (StrUtil.isNotEmpty(tenantId) && StrUtil.isNotEmpty(stepSnapshot)){ 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())) { if (ObjectUtil.isNull(upload) || StringUtils.isBlank(upload.getId())) {
throw new RuntimeException("截图文件上传信息为空"); throw new RuntimeException("截图文件上传信息为空");
} }
log.debug("截图文件上传结果,{}", JSON.toJSONString(upload)); log.debug("截图文件上传结果,{}", JSON.toJSONString(upload));
stepRet.setActualImgUri(upload.getUrlPath()); stepRet.setActualImgUri(upload.getUrl());
} }
} catch (Exception e) { } catch (Exception e) {
log.error("获取步骤执行时截图失败", e); log.error("获取步骤执行时截图失败", e);

View File

@ -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<Runnable>());
savePool = new ThreadPoolExecutor(1, 3,
0L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>());
}
/**
*
* @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);
}
}

View File

@ -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/32uuid[.]
*
* @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());
}
}

View File

@ -120,13 +120,17 @@ public class HttpUtils {
return response.getBody(); 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 filePath
* @param tenantId * @param tenantId
* @return * @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)) { if (StringUtils.isBlank(tenantId)) {
throw new ExecuteException("上传资源失败:缺少租户信息"); throw new ExecuteException("上传资源失败:缺少租户信息");
} }
@ -141,6 +145,9 @@ public class HttpUtils {
multipartMap.add("tenantId", tenantId); multipartMap.add("tenantId", tenantId);
multipartMap.add("objId", objId); multipartMap.add("objId", objId);
multipartMap.add("businessCode", businessCode); multipartMap.add("businessCode", businessCode);
if (StringUtils.isNotBlank(attachId)) {
multipartMap.add("attachId", attachId);
}
FormHttpMessageConverter converter = new FormHttpMessageConverter(); FormHttpMessageConverter converter = new FormHttpMessageConverter();
converter.addPartConverter(new ResourceHttpMessageConverter()); converter.addPartConverter(new ResourceHttpMessageConverter());
template.getMessageConverters().add(converter); template.getMessageConverters().add(converter);

View File

@ -37,6 +37,11 @@ spring:
pool: pool:
max-active: 5 max-active: 5
max-idle: 5 max-idle: 5
task:
scheduling:
pool:
size: 3
thread-name-prefix: scheduler-task-
management: management:
endpoints: endpoints:

View File

@ -176,6 +176,14 @@
<artifactId>thumbnailator</artifactId> <artifactId>thumbnailator</artifactId>
<version>0.4.8</version> <version>0.4.8</version>
</dependency> </dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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); // 在图片的xy上画上一个直径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();
}
}

View File

@ -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 + '\'' +
'}';
}
}

View File

@ -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<AttachmentDB, String> {
}

View File

@ -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;
}
}

View File

@ -7,6 +7,8 @@ import com.alibaba.fastjson.JSONObject;
import io.appium.java_client.AppiumDriver; import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.ios.IOSDriver; 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.config.MobileProperty;
import net.northking.cctp.upperComputer.deviceManager.screen.AndroidScreenResponseThread; import net.northking.cctp.upperComputer.deviceManager.screen.AndroidScreenResponseThread;
import net.northking.cctp.upperComputer.deviceManager.thread.AndroidDeviceInitThread; import net.northking.cctp.upperComputer.deviceManager.thread.AndroidDeviceInitThread;
@ -40,10 +42,14 @@ import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*; import java.io.*;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.*; import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import static io.appium.java_client.remote.AndroidMobileCapabilityType.RESET_KEYBOARD; import static io.appium.java_client.remote.AndroidMobileCapabilityType.RESET_KEYBOARD;
@ -70,6 +76,9 @@ public class AndroidDebuggerServiceImpl extends AbstractDebuggerService {
private Adb adb; private Adb adb;
@Autowired
private AttachInfoService attachInfoService;
@Value("${appium.server.host:127.0.0.1}") @Value("${appium.server.host:127.0.0.1}")
private String appiumHost; private String appiumHost;
@ -731,11 +740,13 @@ public class AndroidDebuggerServiceImpl extends AbstractDebuggerService {
String tenantId = info.getTenantId(); String tenantId = info.getTenantId();
logger.debug("开始上传截图,任务信息:{}",JSON.toJSONString(info)); logger.debug("开始上传截图,任务信息:{}",JSON.toJSONString(info));
String taskId = info.getTaskId(); 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())) { if (null != upload && StringUtils.isNotBlank(upload.getId())) {
logger.debug("文件上传成功返回id{}", upload.getId()); logger.debug("文件上传成功返回id{}", upload.getId());
path = upload.getUrlPath(); path = upload.getUrl();
} }
} catch (ExecuteException e) { } catch (ExecuteException e) {
logger.error("上传截图失败", e); logger.error("上传截图失败", e);

View File

@ -4,6 +4,8 @@ import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.appium.java_client.AppiumDriver; 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.config.MobileProperty;
import net.northking.cctp.upperComputer.deviceManager.common.PyMobileDevice; import net.northking.cctp.upperComputer.deviceManager.common.PyMobileDevice;
import net.northking.cctp.upperComputer.deviceManager.screen.IosScreenResponseThread; import net.northking.cctp.upperComputer.deviceManager.screen.IosScreenResponseThread;
@ -58,6 +60,9 @@ public class IosDebuggerServiceImpl extends AbstractDebuggerService {
super.setMobileProperty(mobileProperty); super.setMobileProperty(mobileProperty);
} }
@Autowired
private AttachInfoService attachInfoService;
@Override @Override
public Object getUiTree(String deviceId) { public Object getUiTree(String deviceId) {
PhoneEntity phoneEntity = IOSDeviceManager.getInstance().getPhoneEntity(deviceId); PhoneEntity phoneEntity = IOSDeviceManager.getInstance().getPhoneEntity(deviceId);
@ -194,17 +199,19 @@ public class IosDebuggerServiceImpl extends AbstractDebuggerService {
@Override @Override
public String uploadShotAllScreen(DebuggerDeviceInfo info) { public String uploadShotAllScreen(DebuggerDeviceInfo info) {
File file = ScreenShotUtils.getIOSMobileScreenShot(info.getDeviceId()); File file = deviceHandleHelper.getScreenShotFile(info.getDeviceId());
String path = null; String path = null;
try { try {
//租户id //租户id
String tenantId = info.getTenantId(); String tenantId = info.getTenantId();
String taskId = info.getTaskId(); String taskId = info.getTaskId();
logger.debug("开始上传截图,任务信息:{}",JSON.toJSONString(info)); 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())) { if (null != upload && org.apache.commons.lang3.StringUtils.isNotBlank(upload.getId())) {
logger.debug("文件上传成功返回id{}", upload.getId()); logger.debug("文件上传成功返回id{}", upload.getId());
path = upload.getUrlPath(); path = upload.getUrl();
} }
} catch (ExecuteException e) { } catch (ExecuteException e) {
logger.error("截图失败",e); logger.error("截图失败",e);

View File

@ -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<Runnable>());
savePool = new ThreadPoolExecutor(1, 3,
0L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>());
}
/**
*
* @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);
}
}

View File

@ -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/32uuid[.]
*
* @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());
}
}

View File

@ -311,6 +311,7 @@ public class HttpUtils {
} }
return result; return result;
} }
/** /**
* *
* @param filePath * @param filePath
@ -318,6 +319,16 @@ public class HttpUtils {
* @return * @return
*/ */
public static Attachment upload(String url, String filePath, String tenantId, String objId, String businessCode) { 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)) { if (StringUtils.isBlank(tenantId)) {
throw new ExecuteException("上传资源失败:缺少租户信息"); throw new ExecuteException("上传资源失败:缺少租户信息");
} }
@ -330,6 +341,9 @@ public class HttpUtils {
multipartMap.add("tenantId", tenantId); multipartMap.add("tenantId", tenantId);
multipartMap.add("objId", objId); multipartMap.add("objId", objId);
multipartMap.add("businessCode", businessCode); multipartMap.add("businessCode", businessCode);
if (StringUtils.isNotBlank(attachId)) {
multipartMap.add("attachId", attachId);
}
FormHttpMessageConverter converter = new FormHttpMessageConverter(); FormHttpMessageConverter converter = new FormHttpMessageConverter();
converter.addPartConverter(new ResourceHttpMessageConverter()); converter.addPartConverter(new ResourceHttpMessageConverter());
template.getMessageConverters().add(converter); template.getMessageConverters().add(converter);

View File

@ -14,6 +14,29 @@ spring:
jackson: jackson:
serialization: serialization:
write-dates-as-timestamps: true 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: nk:
mobile-computer: mobile-computer:
password: 123456 password: 123456

View File

@ -19,6 +19,7 @@ public class S3File implements NKFile
private String tenantId; private String tenantId;
private String objId; private String objId;
private String businessCode; private String businessCode;
private String storagePath;
public S3File() 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) public S3File(String bucket, String tenantId, String suffixName)
{ {
this.bucket = bucket; this.bucket = bucket;
@ -209,4 +237,12 @@ public class S3File implements NKFile
public void setBusinessCode(String businessCode) { public void setBusinessCode(String businessCode) {
this.businessCode = businessCode; this.businessCode = businessCode;
} }
public String getStoragePath() {
return storagePath;
}
public void setStoragePath(String storagePath) {
this.storagePath = storagePath;
}
} }

View File

@ -24,6 +24,18 @@ public interface SimpleStorageService
* @throws FileUploadException * @throws FileUploadException
*/ */
NKFile upload(String tenant, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode) throws FileUploadException, IOException; 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;
/** /**
* *

View File

@ -73,6 +73,29 @@ public class MinioFileStorage implements SimpleStorageService {
return s3File; 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 public NKFile uploadChunk(String tenantId, MultipartFile multipartFile, String uploadId, String chunkIndex) throws FileUploadException, IOException
{ {
S3File s3File = new S3File(properties.getBucket(), tenantId, multipartFile, uploadId, chunkIndex); S3File s3File = new S3File(properties.getBucket(), tenantId, multipartFile, uploadId, chunkIndex);

View File

@ -74,6 +74,30 @@ public class SeaweedFileStorage implements SimpleStorageService {
return s3File; 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 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()); logger.debug("tenantId:{},uploadId:{},chunkIndex:{},fileName:{},size:{}",tenantId, uploadId, chunkIndex, multipartFile.getOriginalFilename(), multipartFile.getSize());

View File

@ -164,7 +164,8 @@ public class AttachFileCtrl
@RequestParam("file") MultipartFile multipartFile, @RequestParam("file") MultipartFile multipartFile,
@RequestParam("tenantId") String tenantId, @RequestParam("tenantId") String tenantId,
@RequestParam(value = "objId", required = false) String objId, @RequestParam(value = "objId", required = false) String objId,
@RequestParam("businessCode") String businessCode) { @RequestParam("businessCode") String businessCode,
@RequestParam(value = "attachId", required = false) String attachId) {
ResultWrapper<Map<String, Object>> wrapper = new ResultWrapper<>(); ResultWrapper<Map<String, Object>> wrapper = new ResultWrapper<>();
FileBusinessTypeEnum fileBusinessTypeByCode = FileBusinessTypeEnum.getFileBusinessTypeByCode(businessCode); FileBusinessTypeEnum fileBusinessTypeByCode = FileBusinessTypeEnum.getFileBusinessTypeByCode(businessCode);
if (null == fileBusinessTypeByCode) { if (null == fileBusinessTypeByCode) {
@ -176,7 +177,7 @@ public class AttachFileCtrl
return wrapper; return wrapper;
} }
NKSecurityContext.setTenantId(tenantId); NKSecurityContext.setTenantId(tenantId);
return attachFileService.uploadResource(response, multipartFile, objId, fileBusinessTypeByCode); return attachFileService.uploadResource(response, multipartFile, objId, fileBusinessTypeByCode, attachId);
} }
@PostMapping(value = {"/v1/uploadForApp"}, @PostMapping(value = {"/v1/uploadForApp"},

View File

@ -68,7 +68,7 @@ public interface AttachFileService
ResultWrapper<String> mergeChunkFiles(ChunkFiles chunkFiles); ResultWrapper<String> mergeChunkFiles(ChunkFiles chunkFiles);
ResultWrapper<Map<String, Object>> uploadResource(HttpServletResponse response, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode); ResultWrapper<Map<String, Object>> uploadResource(HttpServletResponse response, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode, String attachId);
ResultWrapper<String> update(Map<String, String> file); ResultWrapper<String> update(Map<String, String> file);

View File

@ -104,8 +104,15 @@ public class AttachFileServiceImpl implements AttachFileService
response.setStatus(HttpStatus.NOT_FOUND.value()); response.setStatus(HttpStatus.NOT_FOUND.value());
return; return;
} }
String id = objectId;
Attachment attachment = attachmentService.findByPK(tenantId, 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; boolean check = false;
int i=0; int i=0;
while (i<10){ while (i<10){
@ -115,7 +122,7 @@ public class AttachFileServiceImpl implements AttachFileService
} catch (Exception e) { } catch (Exception e) {
logger.error("等待报错",e); logger.error("等待报错",e);
} }
attachment = attachmentService.findByPK(tenantId, objectId); attachment = attachmentService.findByPK(tenantId, id);
}else{ }else{
check=true; check=true;
break; break;
@ -194,7 +201,7 @@ public class AttachFileServiceImpl implements AttachFileService
} }
@Override @Override
public ResultWrapper<Map<String, Object>> uploadResource(HttpServletResponse response, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode) public ResultWrapper<Map<String, Object>> uploadResource(HttpServletResponse response, MultipartFile multipartFile, String objId, FileBusinessTypeEnum businessCode, String attachId)
{ {
ResultWrapper<Map<String, Object>> resultWrapper = new ResultWrapper<>(); ResultWrapper<Map<String, Object>> resultWrapper = new ResultWrapper<>();
resultWrapper.setData(new HashMap<>()); resultWrapper.setData(new HashMap<>());
@ -202,7 +209,7 @@ public class AttachFileServiceImpl implements AttachFileService
String userId = NKSecurityContext.getUserId(); String userId = NKSecurityContext.getUserId();
try try
{ {
NKFile nkFile = storageService.upload(tenantId, multipartFile, objId, businessCode); NKFile nkFile = storageService.upload(tenantId, multipartFile, objId, businessCode, attachId);
Attachment attachment = new Attachment(); Attachment attachment = new Attachment();
BeanUtils.copyProperties(nkFile, attachment); BeanUtils.copyProperties(nkFile, attachment);
@ -211,6 +218,7 @@ public class AttachFileServiceImpl implements AttachFileService
attachment.setObjId(objId); attachment.setObjId(objId);
attachment.setBusinessCode(businessCode.getCode()); attachment.setBusinessCode(businessCode.getCode());
attachment.setOverTime(businessCode.getOverTime()); attachment.setOverTime(businessCode.getOverTime());
attachment.setStoragePath(attachId);
attachmentService.insert(attachment); attachmentService.insert(attachment);
String urlPath = tenantId + encodeFileId(nkFile.getId()); String urlPath = tenantId + encodeFileId(nkFile.getId());

View File

@ -50,4 +50,6 @@ public interface AttachmentDao extends AttachmentMapper {
List<Attachment> queryByOverTime(@Param("overTime") LocalDateTime overTime, @Param("tableSuffix") String tableSuffix); List<Attachment> queryByOverTime(@Param("overTime") LocalDateTime overTime, @Param("tableSuffix") String tableSuffix);
List<Attachment> queryByBusiness(@Param("date") LocalDate date, @Param("tableSuffix") String tableSuffix); List<Attachment> queryByBusiness(@Param("date") LocalDate date, @Param("tableSuffix") String tableSuffix);
Attachment queryByStoragePath(Attachment attachment);
} }

View File

@ -39,6 +39,10 @@ public class Attachment extends TenantPartition implements NKFile, POJO
* *
*/ */
private String objId; private String objId;
/**
*
*/
private String storagePath;
/** /**
* *
*/ */
@ -219,4 +223,12 @@ public class Attachment extends TenantPartition implements NKFile, POJO
public void setOverTime(Date overTime) { public void setOverTime(Date overTime) {
this.overTime = overTime; this.overTime = overTime;
} }
public String getStoragePath() {
return storagePath;
}
public void setStoragePath(String storagePath) {
this.storagePath = storagePath;
}
} }

View File

@ -173,5 +173,15 @@ public class AttachmentServiceImpl extends TenantPaginationService<Attachment> i
return attachmentDao.findByPK(attachment); 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);
}
} }

View File

@ -86,4 +86,6 @@ public interface AttachmentService extends BasicService<Attachment>
List<Attachment> queryByOverTime(LocalDateTime now); List<Attachment> queryByOverTime(LocalDateTime now);
List<Attachment> queryByBusiness(LocalDate now); List<Attachment> queryByBusiness(LocalDate now);
Attachment queryByStoragePath(String tenantId, String storagePath);
} }

View File

@ -17,6 +17,8 @@
<result column="length" jdbcType="BIGINT" property="length"/> <result column="length" jdbcType="BIGINT" property="length"/>
<!-- 关联对象--> <!-- 关联对象-->
<result column="obj_id" jdbcType="VARCHAR" property="objId"/> <result column="obj_id" jdbcType="VARCHAR" property="objId"/>
<!-- 关联对象-->
<result column="storage_path" jdbcType="VARCHAR" property="storagePath"/>
<!-- 业务编码--> <!-- 业务编码-->
<result column="business_code" jdbcType="VARCHAR" property="businessCode"/> <result column="business_code" jdbcType="VARCHAR" property="businessCode"/>
<!-- 过期时间--> <!-- 过期时间-->
@ -41,6 +43,7 @@
,content_type ,content_type
,length ,length
,obj_id ,obj_id
,storage_path
,business_code ,business_code
,over_time ,over_time
,created_by ,created_by
@ -112,6 +115,9 @@
</if> </if>
<if test="objId != null"> <if test="objId != null">
AND obj_id=#{objId,jdbcType=VARCHAR} AND obj_id=#{objId,jdbcType=VARCHAR}
</if>
<if test="storagePath != null">
AND storage_path=#{storage_path,jdbcType=VARCHAR}
</if> </if>
<if test="businessCode != null"> <if test="businessCode != null">
AND business_code=#{businessCode,jdbcType=VARCHAR} AND business_code=#{businessCode,jdbcType=VARCHAR}
@ -156,6 +162,9 @@
<if test="objId != null"> <if test="objId != null">
obj_id, obj_id,
</if> </if>
<if test="storagePath != null">
storage_path,
</if>
<if test="businessCode != null"> <if test="businessCode != null">
business_code, business_code,
</if> </if>
@ -197,6 +206,9 @@
<if test="objId != null"> <if test="objId != null">
#{objId,jdbcType=VARCHAR}, #{objId,jdbcType=VARCHAR},
</if> </if>
<if test="storagePath != null">
#{storagePath,jdbcType=VARCHAR},
</if>
<if test="businessCode != null"> <if test="businessCode != null">
#{businessCode,jdbcType=VARCHAR}, #{businessCode,jdbcType=VARCHAR},
</if> </if>
@ -233,6 +245,7 @@
content_type, content_type,
length, length,
obj_id, obj_id,
storage_path,
business_code, business_code,
over_time, over_time,
created_by, created_by,
@ -250,6 +263,7 @@
#{item.contentType, jdbcType=VARCHAR}, #{item.contentType, jdbcType=VARCHAR},
#{item.length, jdbcType=BIGINT}, #{item.length, jdbcType=BIGINT},
#{item.objId, jdbcType=VARCHAR}, #{item.objId, jdbcType=VARCHAR},
#{item.storagePath, jdbcType=VARCHAR},
#{item.businessCode, jdbcType=VARCHAR}, #{item.businessCode, jdbcType=VARCHAR},
#{item.overTime, jdbcType=TIMESTAMP}, #{item.overTime, jdbcType=TIMESTAMP},
#{item.createdBy, jdbcType=VARCHAR}, #{item.createdBy, jdbcType=VARCHAR},
@ -278,6 +292,9 @@
<if test="objId != null"> <if test="objId != null">
obj_id = #{objId, jdbcType=VARCHAR}, obj_id = #{objId, jdbcType=VARCHAR},
</if> </if>
<if test="storagePath != null">
storage_path = #{storagePath, jdbcType=VARCHAR},
</if>
<if test="businessCode != null"> <if test="businessCode != null">
business_code = #{businessCode, jdbcType=VARCHAR}, business_code = #{businessCode, jdbcType=VARCHAR},
</if> </if>
@ -327,6 +344,9 @@
<if test="objId != null"> <if test="objId != null">
AND obj_id = #{objId,jdbcType=VARCHAR} AND obj_id = #{objId,jdbcType=VARCHAR}
</if> </if>
<if test="storagePath != null">
AND storage_path = #{storagePath,jdbcType=VARCHAR}
</if>
<if test="businessCode != null"> <if test="businessCode != null">
AND business_code = #{businessCode,jdbcType=VARCHAR} AND business_code = #{businessCode,jdbcType=VARCHAR}
</if> </if>
@ -370,6 +390,9 @@
<if test="objId != null"> <if test="objId != null">
AND obj_id=#{objId,jdbcType=VARCHAR} AND obj_id=#{objId,jdbcType=VARCHAR}
</if> </if>
<if test="storagePath != null">
AND storage_path=#{storagePath,jdbcType=VARCHAR}
</if>
<if test="businessCode != null"> <if test="businessCode != null">
AND business_code=#{businessCode,jdbcType=VARCHAR} AND business_code=#{businessCode,jdbcType=VARCHAR}
</if> </if>

View File

@ -39,6 +39,7 @@
length BIGINT comment '文件长度', length BIGINT comment '文件长度',
business_code varchar(50) DEFAULT NULL, business_code varchar(50) DEFAULT NULL,
obj_id varchar(50) DEFAULT NULL COMMENT '关联对象Id', obj_id varchar(50) DEFAULT NULL COMMENT '关联对象Id',
storage_path varchar(128) DEFAULT NULL COMMENT '存储路径',
over_time DATETIME DEFAULT NULL, over_time DATETIME DEFAULT NULL,
created_by VARCHAR(32) COMMENT '创建人' , created_by VARCHAR(32) COMMENT '创建人' ,
created_time DATETIME COMMENT '创建时间' , created_time DATETIME COMMENT '创建时间' ,
@ -183,4 +184,13 @@
) )
limit 5000 limit 5000
</select> </select>
<select id="queryByStoragePath" resultType="net.northking.cctp.attachment.db.entity.Attachment" parameterType="net.northking.cctp.attachment.db.entity.Attachment">
SELECT
<include refid="Base_Column_List" />
FROM
<include refid="Table_Name" />
WHERE
storage_path = #{storagePath,jdbcType=VARCHAR}
limit 1
</select>
</mapper> </mapper>