diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/config/CustomMultipartFile.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/config/CustomMultipartFile.java new file mode 100644 index 0000000..431803e --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/config/CustomMultipartFile.java @@ -0,0 +1,72 @@ +package com.bonus.ai.config; + +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; + +public class CustomMultipartFile implements MultipartFile { + private final File file; + + public CustomMultipartFile(File file) { + this.file = file; + } + + @Override + public String getName() { + return file.getName(); + } + + @Override + public String getOriginalFilename() { + return file.getName(); // 或根据需要返回不同的名称 + } + + @Override + public String getContentType() { + // 根据文件扩展名返回内容类型 + String name = file.getName(); + if (name.endsWith(".jpg") || name.endsWith(".jpeg")) { + return "image/jpeg"; + } else if (name.endsWith(".png")) { + return "image/png"; + } + return null; // 或者抛出异常 + } + + @Override + public boolean isEmpty() { + return file.length() == 0; + } + + @Override + public long getSize() { + return file.length(); + } + + @Override + public byte[] getBytes() throws IOException { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] bytes = new byte[(int) file.length()]; + fis.read(bytes); + return bytes; + } + } + + @Override + public InputStream getInputStream() throws IOException { + return new FileInputStream(file); + } + + @Override + public void transferTo(File dest) throws IOException, IllegalStateException { + // 实现文件传输的逻辑 + try (FileInputStream fis = new FileInputStream(file); + FileOutputStream fos = new FileOutputStream(dest)) { + byte[] buffer = new byte[1024]; + int length; + while ((length = fis.read(buffer)) > 0) { + fos.write(buffer, 0, length); + } + } + } +} diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/DataSetController.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/DataSetController.java index 6cb39db..dd07580 100644 --- a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/DataSetController.java +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/DataSetController.java @@ -1,20 +1,34 @@ package com.bonus.ai.controller; +import cn.hutool.core.io.IoUtil; +import com.bonus.ai.config.CustomMultipartFile; import com.bonus.ai.domain.*; import com.bonus.ai.service.DataSetService; +import com.bonus.common.core.utils.StringUtils; import com.bonus.common.core.web.controller.BaseController; import com.bonus.common.core.web.domain.AjaxResult; import com.bonus.common.core.web.page.TableDataInfo; import com.bonus.system.api.RemoteFileService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; +import org.apache.poi.openxml4j.opc.internal.FileHelper; +import org.aspectj.util.FileUtil; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.commons.CommonsMultipartFile; import javax.annotation.Resource; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; /** * @author bonus @@ -357,7 +371,7 @@ public class DataSetController extends BaseController { * @return 影响的行数 */ @PostMapping("/insertModel") - public AjaxResult insertModel(@RequestBody AiModelEntity entity) { + public AjaxResult insertModel(AiModelEntity entity) { return dataSetService.insertModel(entity); } @@ -368,7 +382,7 @@ public class DataSetController extends BaseController { * @return 影响的行数 */ @PostMapping("/updateModel") - public AjaxResult updateModel(@RequestBody AiModelEntity entity) { + public AjaxResult updateModel(AiModelEntity entity) { return dataSetService.updateModel(entity); } @@ -474,4 +488,117 @@ public class DataSetController extends BaseController { } + @PostMapping("/uploadZipFiles") + public AjaxResult uploadZipFiles(@RequestParam("files") MultipartFile[] files, @RequestParam("datasetId") Long datasetId) { + List multipartFiles = new ArrayList<>(); + Path tempDir; + + try { + // 创建一个临时目录用于存放解压后的文件 + tempDir = Files.createTempDirectory("uploads"); + + // 遍历上传的压缩文件 + for (MultipartFile file : files) { + processZipFile(file, multipartFiles, tempDir); + } + + // 处理完成后删除临时文件夹 + deleteTempDirectory(tempDir); + + // 将 List 转换为数组,方便后续上传 + MultipartFile[] resultFiles = multipartFiles.toArray(new MultipartFile[0]); + return handleFileUpload(resultFiles, datasetId); + } catch (IOException e) { + // 如果创建临时目录失败,返回错误信息 + return AjaxResult.error("Failed to create temporary directory: " + e.getMessage()); + } + } + + // 处理每个压缩文件,解压并将图片文件添加到列表中 + private void processZipFile(MultipartFile file, List multipartFiles, Path tempDir) { + try (ZipInputStream zis = new ZipInputStream(file.getInputStream())) { + ZipEntry entry; + // 逐个读取压缩文件中的条目 + while ((entry = zis.getNextEntry()) != null) { + // 如果条目不是目录且是图片文件 + if (!entry.isDirectory() && isImageFile(entry.getName())) { + // 创建解压后的图片文件 + File imgFile = new File(tempDir.toFile(), entry.getName()); + imgFile.getParentFile().mkdirs(); // 确保目录存在 + // 将条目内容写入到文件 + try (FileOutputStream fos = new FileOutputStream(imgFile)) { + byte[] buffer = new byte[1024]; + int length; + while ((length = zis.read(buffer)) >= 0) { + fos.write(buffer, 0, length); + } + } + + // 创建 MultipartFile 对象并添加到列表中 + MultipartFile multipartFile = new CustomMultipartFile(imgFile); + multipartFiles.add(multipartFile); + } + zis.closeEntry(); // 关闭当前条目 + } + } catch (IOException e) { + // 抛出运行时异常,包含原始文件名的信息 + throw new RuntimeException("Error processing file: " + file.getOriginalFilename(), e); + } + } + + // 处理文件上传及数据库插入 + private AjaxResult handleFileUpload(MultipartFile[] resultFiles, Long datasetId) { + // 调用远程服务上传文件 + AjaxResult ajaxResult = remoteFileService.uploadFile(resultFiles); + if (ajaxResult.isSuccess()) { + // 上传成功,处理返回的数据 + List> data = (List>) ajaxResult.get("data"); + for (Map map : data) { + // 创建数据集文件实体并插入到数据库 + DataSetFileEntity entity = new DataSetFileEntity(); + // 文件地址 + entity.setFileAddress(map.get("url")); + // 关联的数据集 ID + entity.setDatasetId(datasetId); + // 文件名 + entity.setFileName(map.get("name")); + dataSetService.insertFile(entity); + } + // 返回成功结果 + return AjaxResult.success(); + } else { + // 上传失败,返回错误信息 + return AjaxResult.error("上传文件失败"); + } + } + + // 检查文件名是否为图片文件 + private boolean isImageFile(String fileName) { + String[] extensions = {".jpg", ".jpeg", ".png"}; + // 遍历扩展名,检查文件名是否符合 + for (String ext : extensions) { + if (fileName.toLowerCase().endsWith(ext)) { + return true; + } + } + return false; // 不是图片文件 + } + + // 删除临时目录及其中的文件 + private void deleteTempDirectory(Path tempDir) { + try { + // 遍历临时目录,删除所有文件和子目录 + Files.walk(tempDir) + .sorted(Comparator.reverseOrder()) + .forEach(path -> { + try { + Files.delete(path); + } catch (IOException e) { + e.printStackTrace(); // 打印错误信息 + } + }); + } catch (IOException e) { + e.printStackTrace(); // 打印错误信息 + } + } } diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/AiModelEntity.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/AiModelEntity.java index 23d1b1d..ad74962 100644 --- a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/AiModelEntity.java +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/AiModelEntity.java @@ -4,6 +4,7 @@ import com.bonus.common.core.web.domain.BaseEntity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; import java.util.Date; @@ -13,7 +14,7 @@ import java.util.Date; @Data @AllArgsConstructor @NoArgsConstructor -public class AiModelEntity extends BaseEntity { +public class AiModelEntity { /** * 模型唯一id */ @@ -26,10 +27,6 @@ public class AiModelEntity extends BaseEntity { * 模型版本 */ private String modelVersion; - /** - * 分任务类型id - */ - private Long subTaskTypeId; /** * 模型类型 */ @@ -57,10 +54,13 @@ public class AiModelEntity extends BaseEntity { /** * 模型相对地址 */ + private MultipartFile[] modelFile; + private String modelAddress; /** * 使用手册相对地址 */ + private MultipartFile[] userGuideFile; private String userGuide; /** * 描述 @@ -70,4 +70,8 @@ public class AiModelEntity extends BaseEntity { * 算法选择 */ private String algorithm; + + private String createBy; + + private Date createTime; } diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/mapper/DataSetMapper.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/mapper/DataSetMapper.java index 0c87544..d11546e 100644 --- a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/mapper/DataSetMapper.java +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/mapper/DataSetMapper.java @@ -125,7 +125,9 @@ public interface DataSetMapper { * @param datasetFile 数据集文件实体 * @return 影响的行数 */ - int updateFile(DataSetFileEntity datasetFile); + int updateFile(@Param("datasetId") Long datasetId, + @Param("updateBy") String updateBy, + @Param("fileIds") Long[] fileIds); /** * 根据 ID 删除数据集文件(逻辑删除) diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/DataSetServiceImpl.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/DataSetServiceImpl.java index 7234600..11449e5 100644 --- a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/DataSetServiceImpl.java +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/DataSetServiceImpl.java @@ -3,14 +3,19 @@ package com.bonus.ai.service.impl; import com.bonus.ai.domain.*; import com.bonus.ai.mapper.DataSetMapper; import com.bonus.ai.service.DataSetService; +import com.bonus.common.core.domain.R; import com.bonus.common.core.web.domain.AjaxResult; import com.bonus.common.security.utils.SecurityUtils; +import com.bonus.system.api.RemoteFileService; +import com.bonus.system.api.domain.SysFile; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.util.Collections; import java.util.List; +import java.util.Map; /** * @author bonus @@ -21,6 +26,9 @@ public class DataSetServiceImpl implements DataSetService { @Resource private DataSetMapper mapper; + @Resource + private RemoteFileService remoteFileService; + /** * 根据数据集 ID 查询对应的数据集信息。 * @@ -230,7 +238,7 @@ public class DataSetServiceImpl implements DataSetService { @Override public AjaxResult updateFile(DataSetFileEntity datasetFile) { try { - int i = mapper.updateFile(datasetFile); + int i = mapper.updateFile(datasetFile.getDatasetId(), datasetFile.getUpdateBy(), datasetFile.getFileIds()); return i > 0 ? AjaxResult.success("移动成功") : AjaxResult.error("移动失败"); } catch (Exception e) { return AjaxResult.error("移动失败"); @@ -382,6 +390,26 @@ public class DataSetServiceImpl implements DataSetService { public AjaxResult insertModel(AiModelEntity entity) { try { entity.setCreateBy(SecurityUtils.getUsername()); + AjaxResult ajaxResult = remoteFileService.uploadFile(entity.getModelFile()); + if (ajaxResult.isSuccess()) { + List> data = (List>) ajaxResult.get("data"); + for (Map map : data) { + entity.setModelAddress(map.get("url")); + } + } else { + return AjaxResult.error("上传文件失败"); + } + + AjaxResult userGuide = remoteFileService.uploadFile(entity.getUserGuideFile()); + if (userGuide.isSuccess()) { + List> data = (List>) userGuide.get("data"); + for (Map map : data) { + entity.setUserGuide(map.get("url")); + } + } else { + + return AjaxResult.error("上传文件失败"); + } int i = mapper.insertModel(entity); return i > 0 ? AjaxResult.success("新增成功") : AjaxResult.error("新增失败"); } catch (Exception e) { @@ -398,6 +426,29 @@ public class DataSetServiceImpl implements DataSetService { @Override public AjaxResult updateModel(AiModelEntity entity) { try { + if (entity.getModelFile().length > 0) { + AjaxResult ajaxResult = remoteFileService.uploadFile(entity.getModelFile()); + if (ajaxResult.isSuccess()) { + List> data = (List>) ajaxResult.get("data"); + for (Map map : data) { + entity.setModelAddress(map.get("url")); + } + } else { + return AjaxResult.error("上传文件失败"); + } + } + if (entity.getUserGuideFile().length > 0) { + AjaxResult userGuide = remoteFileService.uploadFile(entity.getUserGuideFile()); + if (userGuide.isSuccess()) { + List> data = (List>) userGuide.get("data"); + for (Map map : data) { + entity.setUserGuide(map.get("url")); + } + } else { + + return AjaxResult.error("上传文件失败"); + } + } int i = mapper.updateModel(entity); return i > 0 ? AjaxResult.success("修改成功") : AjaxResult.error("修改失败"); } catch (Exception e) {