|
@@ -8,15 +8,33 @@ import com.taais.biz.domain.bo.DataBo;
|
|
|
import com.taais.biz.domain.vo.DataVo;
|
|
|
import com.taais.biz.mapper.DataMapper;
|
|
|
import com.taais.biz.service.IDataService;
|
|
|
+import com.taais.common.core.config.TaaisConfig;
|
|
|
+import com.taais.common.core.core.domain.CommonResult;
|
|
|
import com.taais.common.core.core.page.PageResult;
|
|
|
import com.taais.common.core.utils.MapstructUtils;
|
|
|
+import com.taais.common.core.utils.StringUtils;
|
|
|
+import com.taais.common.core.utils.file.FileUploadUtils;
|
|
|
+import com.taais.common.core.utils.file.FileUtils;
|
|
|
+import com.taais.common.core.utils.file.UnPackedUtil;
|
|
|
import com.taais.common.orm.core.page.PageQuery;
|
|
|
import com.taais.common.orm.core.service.impl.BaseServiceImpl;
|
|
|
import jakarta.annotation.Resource;
|
|
|
+import net.lingala.zip4j.model.FileHeader;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
-import java.util.Arrays;
|
|
|
-import java.util.List;
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.nio.file.Path;
|
|
|
+import java.nio.file.Paths;
|
|
|
+import java.nio.file.attribute.BasicFileAttributes;
|
|
|
+import java.time.Instant;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
|
import static com.taais.biz.domain.table.DataTableDef.DATA;
|
|
|
|
|
@@ -28,6 +46,11 @@ import static com.taais.biz.domain.table.DataTableDef.DATA;
|
|
|
*/
|
|
|
@Service
|
|
|
public class DataServiceImpl extends BaseServiceImpl<DataMapper, Data> implements IDataService {
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(DataServiceImpl.class);
|
|
|
+ private static final String ZIP = ".zip";
|
|
|
+ private static final String RAR = ".rar";
|
|
|
+ private static final String TXT = ".txt";
|
|
|
+ private static final String[] VALID_EXTENSIONS = {".jpg", ".jpeg", ".png"};
|
|
|
@Resource
|
|
|
private DataMapper dataMapper;
|
|
|
|
|
@@ -39,33 +62,33 @@ public class DataServiceImpl extends BaseServiceImpl<DataMapper, Data> implement
|
|
|
private QueryWrapper buildQueryWrapper(DataBo dataBo) {
|
|
|
QueryWrapper queryWrapper = super.buildBaseQueryWrapper();
|
|
|
queryWrapper.and(DATA.NAME.like
|
|
|
- (dataBo.getName()));
|
|
|
+ (dataBo.getName()));
|
|
|
queryWrapper.and(DATA.DATA_TYPE.eq
|
|
|
- (dataBo.getDataType()));
|
|
|
+ (dataBo.getDataType()));
|
|
|
queryWrapper.and(DATA.FILE_TYPE.eq
|
|
|
- (dataBo.getFileType()));
|
|
|
+ (dataBo.getFileType()));
|
|
|
queryWrapper.and(DATA.OBJECT_TYPE.eq
|
|
|
- (dataBo.getObjectType()));
|
|
|
+ (dataBo.getObjectType()));
|
|
|
queryWrapper.and(DATA.OBJECT_SUBTYPE.eq
|
|
|
- (dataBo.getObjectSubtype()));
|
|
|
+ (dataBo.getObjectSubtype()));
|
|
|
queryWrapper.and(DATA.BATCH_NUM.eq
|
|
|
- (dataBo.getBatchNum()));
|
|
|
+ (dataBo.getBatchNum()));
|
|
|
queryWrapper.and(DATA.SCENE.eq
|
|
|
- (dataBo.getScene()));
|
|
|
+ (dataBo.getScene()));
|
|
|
queryWrapper.and(DATA.DATA_SOURCE.eq
|
|
|
- (dataBo.getDataSource()));
|
|
|
+ (dataBo.getDataSource()));
|
|
|
queryWrapper.and(DATA.GATHER_TIME.eq
|
|
|
- (dataBo.getGatherTime()));
|
|
|
+ (dataBo.getGatherTime()));
|
|
|
queryWrapper.and(DATA.GATHER_SPOT.eq
|
|
|
- (dataBo.getGatherSpot()));
|
|
|
+ (dataBo.getGatherSpot()));
|
|
|
queryWrapper.and(DATA.URL.eq
|
|
|
- (dataBo.getUrl()));
|
|
|
+ (dataBo.getUrl()));
|
|
|
queryWrapper.and(DATA.LABELURL.eq
|
|
|
- (dataBo.getLabelurl()));
|
|
|
+ (dataBo.getLabelurl()));
|
|
|
queryWrapper.and(DATA.INCREMENT.eq
|
|
|
- (dataBo.getIncrement()));
|
|
|
+ (dataBo.getIncrement()));
|
|
|
queryWrapper.and(DATA.LABELED.eq
|
|
|
- (dataBo.getLabeled()));
|
|
|
+ (dataBo.getLabeled()));
|
|
|
|
|
|
return queryWrapper;
|
|
|
}
|
|
@@ -78,7 +101,7 @@ public class DataServiceImpl extends BaseServiceImpl<DataMapper, Data> implement
|
|
|
*/
|
|
|
@Override
|
|
|
public DataVo selectById(Long id) {
|
|
|
- return this.getOneAs(query().where(DATA.ID.eq(id)), DataVo.class);
|
|
|
+ return this.getOneAs(query().where(DATA.ID.eq(id)), DataVo.class);
|
|
|
|
|
|
}
|
|
|
|
|
@@ -91,7 +114,146 @@ public class DataServiceImpl extends BaseServiceImpl<DataMapper, Data> implement
|
|
|
@Override
|
|
|
public List<DataVo> selectList(DataBo dataBo) {
|
|
|
QueryWrapper queryWrapper = buildQueryWrapper(dataBo);
|
|
|
- return this.listAs(queryWrapper, DataVo.class);
|
|
|
+ return this.listAs(queryWrapper, DataVo.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CommonResult<Boolean> uploadDataInfo(MultipartFile file, Data dataInfo) {
|
|
|
+ //1.检测是否有重复的批次号
|
|
|
+ QueryWrapper query = query();
|
|
|
+ query.eq(Data::getBatchNum, dataInfo.getBatchNum());
|
|
|
+ long count = dataMapper.selectCountByQuery(query);
|
|
|
+ if (count > 0) {
|
|
|
+ return CommonResult.fail("检测出重复批次号,请仔细检查后重新导入!");
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ Boolean labeled = dataInfo.getLabeled();
|
|
|
+ //2.解压图片并检查
|
|
|
+ String originalFilename = file.getOriginalFilename();
|
|
|
+ assert originalFilename != null;
|
|
|
+ String suffix = StringUtils.substring(originalFilename, originalFilename.lastIndexOf("."), originalFilename.length());
|
|
|
+ // 解压
|
|
|
+ String basedir = TaaisConfig.getUploadPath();
|
|
|
+ // 解压目录
|
|
|
+ File zipOrRarTemp = FileUploadUtils.getAbsoluteFile(basedir, FileUploadUtils.extractFilename2(file));
|
|
|
+ String destZip = zipOrRarTemp.getAbsolutePath();
|
|
|
+ file.transferTo(Paths.get(destZip));
|
|
|
+ String dest = zipOrRarTemp.getParent();
|
|
|
+ // 解压图片集合
|
|
|
+ List<File> extractedImagesFileList = new ArrayList<>();
|
|
|
+ if (ZIP.equals(suffix)) {
|
|
|
+ //添加解压目录
|
|
|
+ for (FileHeader fileHeader : UnPackedUtil.unPackZip(zipOrRarTemp, dest)) {
|
|
|
+ initFileInfo(dest, extractedImagesFileList, fileHeader.isDirectory(), fileHeader.getFileName());
|
|
|
+ }
|
|
|
+ } else if (RAR.equals(suffix)) {
|
|
|
+ //添加解压目录
|
|
|
+ for (com.github.junrar.rarfile.FileHeader fileHeader : UnPackedUtil.unPackRar(zipOrRarTemp, dest)) {
|
|
|
+ initFileInfo(dest, extractedImagesFileList, fileHeader.isDirectory(), fileHeader.getFileName());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return CommonResult.fail("请上传.zip、.rar压缩文件。!");
|
|
|
+ }
|
|
|
+
|
|
|
+ //检测图片文件是否为空
|
|
|
+ if (extractedImagesFileList.isEmpty()) {
|
|
|
+ return CommonResult.fail("压缩文件图片为空,请检查后重新上传!");
|
|
|
+ }
|
|
|
+
|
|
|
+ //3获取ID集合
|
|
|
+ List<Long> ids = dataMapper.getIds(extractedImagesFileList.size());
|
|
|
+ if (ids.isEmpty()) {
|
|
|
+ return CommonResult.fail("系统异常!");
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Boolean> labeledList = new ArrayList<>();
|
|
|
+ List<Data> dataList = new ArrayList<>();
|
|
|
+ AtomicInteger countSize = new AtomicInteger();
|
|
|
+ extractedImagesFileList.forEach(fileInfo -> {
|
|
|
+ //获取ID
|
|
|
+ Long id = ids.get(countSize.get());
|
|
|
+ Data data = new Data();
|
|
|
+ //拷贝dataInfo
|
|
|
+ BeanUtils.copyProperties(dataInfo, data);
|
|
|
+ //检测是否标注
|
|
|
+ if (checkLabeled(fileInfo.getPath())) {
|
|
|
+ labeledList.add(Boolean.TRUE);
|
|
|
+ data.setLabeled(Boolean.TRUE);
|
|
|
+ } else {
|
|
|
+ labeledList.add(Boolean.FALSE);
|
|
|
+ data.setLabeled(Boolean.FALSE);
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ Path path = Paths.get(fileInfo.getAbsolutePath());
|
|
|
+ // 使用Files类的readAttributes方法获取文件的基本属性
|
|
|
+ BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
|
|
|
+ // 获取文件的创建时间
|
|
|
+ Instant creationTime = attrs.creationTime().toInstant();
|
|
|
+ // 将Instant转换为Date
|
|
|
+ Date date = Date.from(creationTime);
|
|
|
+ //设置文件创建时间
|
|
|
+ data.setId(id);
|
|
|
+ data.setGatherTime(date);
|
|
|
+ data.setName(fileInfo.getName());
|
|
|
+ //更改图片文件名称
|
|
|
+ String fileHeaderSuffix = StringUtils.substring(fileInfo.getName(), fileInfo.getName().lastIndexOf("."), fileInfo.getName().length());
|
|
|
+ String destInfo = fileInfo.getPath().replaceAll(fileInfo.getName(), "");
|
|
|
+ File newFile = new File(destInfo, id + fileHeaderSuffix);
|
|
|
+ File odlFile = new File(destInfo, fileInfo.getName());
|
|
|
+ log.info("更改用户上传图片文件名称:{}", odlFile.renameTo(newFile));
|
|
|
+ String imagePath = FileUploadUtils.getPathFileName(destInfo, id + fileHeaderSuffix);
|
|
|
+ data.setUrl(imagePath);
|
|
|
+ //该图片有标注,更改标注文件名称
|
|
|
+ if (data.getLabeled()) {
|
|
|
+ String labeledPath = fileInfo.getPath().replaceFirst("[.][^.]+$", "") + ".txt";
|
|
|
+ File labeledNewFile = new File(destInfo, id + ".txt");
|
|
|
+ File labeledOdlFile = new File(labeledPath);
|
|
|
+ log.info("更改用户上传标注文件名称:{}", labeledOdlFile.renameTo(labeledNewFile));
|
|
|
+ String labelUrl = FileUploadUtils.getPathFileName(destInfo, id + ".txt");
|
|
|
+ data.setLabelurl(labelUrl);
|
|
|
+ }
|
|
|
+ dataList.add(data);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ countSize.getAndIncrement();
|
|
|
+ });
|
|
|
+ //是否选择已标注,如果已标注则需要检测所有图片是否标注
|
|
|
+ if (!labeledList.isEmpty() && labeled) {
|
|
|
+ // 已标注数量
|
|
|
+ long unmarkedCount = labeledList.stream().filter(Boolean.FALSE::equals).count();
|
|
|
+ // 未标注数量
|
|
|
+ long markedCount = labeledList.stream().filter(Boolean.TRUE::equals).count();
|
|
|
+ // 如果存在未标注的数据,则返回错误信息
|
|
|
+ if (unmarkedCount > 0) {
|
|
|
+ String format = String.format("错误: 已标注文件 %d 个,未标注文件 %d 个", markedCount, unmarkedCount);
|
|
|
+ return CommonResult.fail(format);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dataMapper.insertBatch(dataList);
|
|
|
+ FileUtils.deleteFile(destZip);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("[uploadDataInfo]数据集处理出现未知异常.e:", e);
|
|
|
+ return CommonResult.fail("系统异常!");
|
|
|
+ }
|
|
|
+ return CommonResult.success("数据集上传成功!");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initFileInfo(String dest, List<File> extractedImagesFileList, boolean directory, String fileName) {
|
|
|
+ if (!directory) {
|
|
|
+ String fileHeaderSuffix = StringUtils.substring(fileName, fileName.lastIndexOf("."), fileName.length());
|
|
|
+ if (Arrays.asList(VALID_EXTENSIONS).contains(fileHeaderSuffix)) {
|
|
|
+ extractedImagesFileList.add(new File(dest, fileName));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean checkLabeled(String pathFileName) {
|
|
|
+ Path newPath = Paths.get(pathFileName.replaceFirst("[.][^.]+$", "") + ".txt");
|
|
|
+ // 检查替换后的文件是否存在
|
|
|
+ boolean exists = Files.exists(newPath);
|
|
|
+ log.info("[checkLabeled]图片文件路径名称:{},标注文件路径名称:{},是否标注:{}", pathFileName, newPath, exists);
|
|
|
+ return exists;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -103,7 +265,7 @@ public class DataServiceImpl extends BaseServiceImpl<DataMapper, Data> implement
|
|
|
@Override
|
|
|
public PageResult<DataVo> selectPage(DataBo dataBo) {
|
|
|
QueryWrapper queryWrapper = buildQueryWrapper(dataBo);
|
|
|
- Page<DataVo> page = this.pageAs(PageQuery.build(), queryWrapper, DataVo.class);
|
|
|
+ Page<DataVo> page = this.pageAs(PageQuery.build(), queryWrapper, DataVo.class);
|
|
|
return PageResult.build(page);
|
|
|
}
|
|
|
|
|
@@ -128,10 +290,10 @@ public class DataServiceImpl extends BaseServiceImpl<DataMapper, Data> implement
|
|
|
*/
|
|
|
@Override
|
|
|
public boolean update(DataBo dataBo) {
|
|
|
- Data data =MapstructUtils.convert(dataBo, Data. class);
|
|
|
- if (ObjectUtil.isNotNull(data) && ObjectUtil.isNotNull(data.getId())){
|
|
|
+ Data data = MapstructUtils.convert(dataBo, Data.class);
|
|
|
+ if (ObjectUtil.isNotNull(data) && ObjectUtil.isNotNull(data.getId())) {
|
|
|
boolean updated = this.updateById(data);
|
|
|
- return updated;
|
|
|
+ return updated;
|
|
|
}
|
|
|
return false;
|
|
|
}
|