@xingjs@20241224@添加解析CSV文件相关实体类、方法;添加文件上传配置;添加开发文件上传相关工具类
已添加2个文件
已修改3个文件
559 ■■■■■ 文件已修改
src/main/java/com/se/simu/controller/FilesUploadController.java 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/simu/controller/SimuController.java 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/simu/service/SimuFilesService.java 213 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-prod.yml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-zyy.yml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/simu/controller/FilesUploadController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,183 @@
package com.se.simu.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
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.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.zip.ZipEntry;
@Api(tags = "0-文件相关接口")
@Slf4j
@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/v1/files")
public class FilesUploadController {
    @Value("${simu-app.filePath}")
    //  private final String uploadedFolder = "D:/home/scheme/upload";
    private String uploadedFolder;
    @ApiOperation("0-文件上传地址")
    @GetMapping("/getUploadPath")
    public ResponseEntity<String> getUploadPath() throws Exception {
        return ResponseEntity.ok("文件上传地址为:" + uploadedFolder);
    }
    @ApiOperation("1-上传单个文件")
    @ApiImplicitParam(name = "filePathName", value = "文件夹名称", required = true, dataType = "String", paramType = "query", example = "upload", dataTypeClass = String.class)
    @PostMapping("/uploadSingleFile")
    public ResponseEntity<String> uploadSingleFile(@RequestParam("file") MultipartFile file, @RequestParam("filePathName") String filePathName) throws IOException {
        if (file.isEmpty()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("文件不能为空");
        }
        // åˆ¤æ–­ filePathName æ˜¯å¦ä¸ºç©º
        if (filePathName == null || filePathName.isEmpty()) {
            filePathName = "upload";
            //return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("文件夹名称不能为空");
        }
        String targetDir = Paths.get(uploadedFolder, filePathName).toString();
        log.info("目标目录: {}", targetDir);
        createDirectoriesIfNotExists(targetDir);
        try {
            file.transferTo(Paths.get(targetDir, file.getOriginalFilename()));
            return ResponseEntity.ok("文件上传成功");
        } catch (IOException e) {
            log.error("文件上传失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败");
        }
    }
    @ApiOperation("2-上传多个文件")
    @ApiImplicitParam(name = "filePathName", value = "文件夹名称", required = true, dataType = "String", paramType = "query", example = "upload", dataTypeClass = String.class)
    @PostMapping("/uploadMultipleFiles")
    public ResponseEntity<String> uploadMultipleFiles(List<MultipartFile> files, @RequestParam("filePathName") String filePathName) throws IOException {
        // åˆ¤æ–­ filePathName æ˜¯å¦ä¸ºç©º
        if (filePathName == null || filePathName.isEmpty()) {
            //  return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("文件夹名称不能为空");
            filePathName = "upload";
        }
        // ä¸Šä¼ æ–‡ä»¶è·¯å¾„
        String targetDir = Paths.get(uploadedFolder, filePathName).toString();
        log.info("目标目录: {}", targetDir);
        createDirectoriesIfNotExists(targetDir);
        CompletableFuture<Void> allUploadTasks = CompletableFuture.allOf(files.stream()
                .map(file -> CompletableFuture.runAsync(() -> {
                    try {
                        file.transferTo(Paths.get(targetDir, file.getOriginalFilename()));
                    } catch (IOException e) {
                        log.error("文件上传失败", e);
                        throw new RuntimeException("文件上传失败");
                    }
                })).toArray(CompletableFuture[]::new));
        try {
            allUploadTasks.get();
            return ResponseEntity.ok("所有文件上传成功!上传目录为:" + targetDir);
        } catch (InterruptedException | ExecutionException e) {
            log.error("文件上传失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败");
        }
    }
    @ApiOperation("2-1上传多个文件")
    @ApiImplicitParam(name = "filePathName", value = "文件夹名称", required = true, dataType = "String", paramType = "query", example = "upload", dataTypeClass = String.class)
    @PostMapping("/uploadMultipleFile")
    public ResponseEntity<String> uploadMultipleFile(List<MultipartFile> files, @RequestParam("filePathName") String filePathName) throws IOException {
        // ä¸Šä¼ æ–‡ä»¶è·¯å¾„
        String targetDir = Paths.get(uploadedFolder, filePathName).toString();
        log.info("目标目录: {}", targetDir);
        createDirectoriesIfNotExists(targetDir);
        try {
            for (MultipartFile file : files) {
                String fileName = file.getOriginalFilename();
                File targetFile = new File(targetDir, fileName);
                file.transferTo(targetFile);
            }
            return ResponseEntity.ok("所有文件上传成功!上传目录为:" + targetDir);
        } catch (IOException e) {
            log.error("文件上传失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败");
        }
    }
    private File newFile(File destinationDir, ZipEntry zipEntry) throws Exception {
        File destFile = new File(destinationDir, zipEntry.getName());
        String destDirPath = destinationDir.getCanonicalPath();
        String destFilePath = destFile.getCanonicalPath();
        if (!destFilePath.startsWith(destDirPath + File.separator)) {
            throw new Exception("Entry is outside of the target dir: " + zipEntry.getName());
        }
        return destFile;
    }
    /**
     * æŒ‰æ–‡ä»¶è·¯å¾„删除文件夹
     * é€’归删除文件夹及文件的方法
     *
     * @param folder æ–‡ä»¶å¤¹
     */
    private void deleteFolderByFilePath(File folder) {
        if (folder.exists()) {
            File[] files = folder.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        // é€’归删除子文件夹
                        deleteFolderByFilePath(file);
                    } else {
                        // åˆ é™¤æ–‡ä»¶
                        file.delete();
                    }
                }
            }
            // åˆ é™¤æ–‡ä»¶å¤¹æœ¬èº«
            folder.delete();
        }
    }
    /**
     * @param targetDir ç›®æ ‡ç›®å½•
     * @throws IOException
     */
    private void createDirectoriesIfNotExists(String targetDir) throws IOException {
        Path path = Paths.get(targetDir);
        if (!Files.exists(path)) {
            Files.createDirectories(path);
        }
    }
    private Boolean directoriesIfNotExists(String targetDir) throws IOException {
        Path path = Paths.get(targetDir);
        if (!Files.exists(path)) {
            // Files.createDirectories(path);
            return false;
        } else {
            return true;
        }
    }
}
src/main/java/com/se/simu/controller/SimuController.java
@@ -1,6 +1,7 @@
package com.se.simu.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.se.simu.config.PropertiesConfig;
import com.se.simu.domain.dto.GeDb;
import com.se.simu.domain.dto.GeLayer;
import com.se.simu.domain.po.DataPo;
@@ -8,19 +9,26 @@
import com.se.simu.domain.vo.CreateSimuVo;
import com.se.simu.domain.vo.R;
import com.se.simu.domain.vo.SimuVo;
import com.se.simu.service.GedbService;
import com.se.simu.service.ResultService;
import com.se.simu.service.SimuService;
import com.se.simu.service.UwService;
import com.se.simu.service.*;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
@Api(tags = "仿真管理")
@Slf4j
@@ -36,6 +44,12 @@
    @Resource
    SimuService simuService;
    @Resource
    SimuFilesService simuFilesService;
    @Resource
    PropertiesConfig config;
    @Resource
    ResultService resultService;
@@ -164,4 +178,135 @@
            return fail(ex, false);
        }
    }
    @ApiOperation("test-上传多个文件")
    @ApiImplicitParam(name = "schemeName", value = "方案名称", required = true, dataType = "String", paramType = "query", example = "edf243d3-3bec-4c51-9930-1ba862d9b5a3", dataTypeClass = String.class)
    @PostMapping("/uploadMultipleFiles")
    public ResponseEntity<String> uploadMultipleFiles(List<MultipartFile> files, @RequestParam("schemeName") String schemeName) throws IOException {
        // ä¸Šä¼ æ–‡ä»¶è·¯å¾„
        String targetDir = Paths.get(config.getOutPath(), schemeName).toString();
        log.info("目标目录: {}", targetDir);
        createDirectoriesIfNotExists(targetDir);
        List<CompletableFuture<Void>> uploadTasks = files.stream()
                .map(file -> CompletableFuture.runAsync(() -> {
                    try {
                        file.transferTo(Paths.get(targetDir, file.getOriginalFilename()));
                    } catch (IOException e) {
                        log.error("文件上传失败", e);
                        throw new RuntimeException("文件上传失败");
                    }
                }))
                .collect(Collectors.toList());
        CompletableFuture<Void> allUploadTasks = CompletableFuture.allOf(uploadTasks.toArray(new CompletableFuture[0]));
        try {
            allUploadTasks.get();
            return ResponseEntity.ok("所有文件上传成功");
        } catch (InterruptedException | ExecutionException e) {
            log.error("文件上传失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败");
        }
    }
    /**
     * @param targetDir ç›®æ ‡ç›®å½•
     * @throws IOException
     */
    private void createDirectoriesIfNotExists(String targetDir) throws IOException {
        Path path = Paths.get(targetDir);
        if (!Files.exists(path)) {
            Files.createDirectories(path);
        }
    }
    /**
     * æ–‡ä»¶åˆ›å»ºæ¨¡æ‹Ÿ
     *
     * @param vo VO
     * @return {@link R}<{@link Object}>
     */
    @ApiOperation(value = "文件创建")
    @PostMapping(value = "/file_create", produces = "application/json; charset=UTF-8")
    public R<Object> fileCreate(List<MultipartFile> files,@RequestBody @ApiParam("创建仿真视图类") CreateSimuVo vo) throws IOException {
        // ä¸Šä¼ æ–‡ä»¶è·¯å¾„
        String targetDir = Paths.get(config.getOutPath(), "files").toString();
        log.info("目标目录: {}", targetDir);
        createDirectoriesIfNotExists(targetDir);
        List<CompletableFuture<Void>> uploadTasks = files.stream()
                .map(file -> CompletableFuture.runAsync(() -> {
                    try {
                        file.transferTo(Paths.get(targetDir, file.getOriginalFilename()));
                    } catch (IOException e) {
                        log.error("文件上传失败", e);
                        throw new RuntimeException("文件上传失败");
                    }
                }))
                .collect(Collectors.toList());
        CompletableFuture<Void> allUploadTasks = CompletableFuture.allOf(uploadTasks.toArray(new CompletableFuture[0]));
        try {
            allUploadTasks.get();
            log.info("文件上传成功");
        } catch (InterruptedException | ExecutionException e) {
            log.error("文件上传失败", e);
        }
        try {
            if (null == vo.getTotal() || vo.getTotal() < 1 || vo.getTotal() > 1000) {
                return fail("降雨量不能为空,且取值在1~1000之间");
            }
            if (null == vo.getDuration() || vo.getDuration() < 1 || vo.getDuration() > 10080) {
                return fail("仿真时长不能为空,且取值在1~10080之间");
            }
            if (null == vo.getMinx() || null == vo.getMiny() || null == vo.getMaxx() || null == vo.getMaxy()) {
                return fail("选择范围不能为空", false);
            }
            if (null == vo.getPid() || vo.getPid() < 0) {
                vo.setPid(0);
            }
            if (null == vo.getNum() || vo.getNum() < 1) {
                vo.setNum(simuService.getMaxId() + 1);
            }
            if (null == vo.getPid() || vo.getPid() < 0) {
                vo.setPid(0);
            }
            if (null == vo.getStartTime()) {
                vo.setStartTime(new Date());
            }
            if (vo.getPid() > 0) {
                SimuPo pp = simuService.getSimuByPid(vo.getPid());
                if (null == pp) {
                    return fail("pid不存在");
                }
                if (null == vo.getFloodStart() || vo.getFloodStart() < 1 || vo.getFloodStart() > vo.getDuration() * 60) {
                    return fail("防汛开始时间不能为空,且取值在1~" + (vo.getDuration() * 60) + "之间");
                }
                if (null == vo.getFloodEnd() || vo.getFloodEnd() < vo.getFloodStart() || vo.getFloodEnd() > vo.getDuration() * 60) {
                    return fail("防汛结束时间不能为空,且取值在" + vo.getFloodStart() + "~" + (vo.getDuration() * 60) + "之间");
                }
                if (null == vo.getFloodHeight() || vo.getFloodHeight() < 1 || vo.getFloodHeight() > 2000) {
                    return fail("防汛高度不能为空,且取值在1~2000之间");
                }
                if (!FLOOD_TYPE.contains(vo.getFloodType())) {
                    return fail("防汛类型不能为空,且只能是沙袋和防水板");
                }
                if (null == vo.getFloodMinx() || null == vo.getFloodMiny() || null == vo.getFloodMaxx() || null == vo.getFloodMaxy()) {
                    return fail("防汛范围不能为空", false);
                }
            }
            boolean flag = simuFilesService.createByfiles(vo);
            return success(flag, flag ? "成功" : "失败");
        } catch (Exception ex) {
            return fail(ex, null);
        }
    }
}
src/main/java/com/se/simu/service/SimuFilesService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,213 @@
package com.se.simu.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.se.simu.config.PropertiesConfig;
import com.se.simu.domain.dto.GeDb;
import com.se.simu.domain.po.DataPo;
import com.se.simu.domain.po.SimuPo;
import com.se.simu.domain.vo.CreateSimuVo;
import com.se.simu.domain.vo.SimuVo;
import com.se.simu.helper.StringHelper;
import com.se.simu.helper.WebHelper;
import com.se.simu.mapper.SimuMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.File;
import java.sql.Timestamp;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * SIMU æ–‡ä»¶æœåŠ¡
 *
 * @author xingjinshuang@smartearth.cn
 * @date 2024/12/24
 */
@Slf4j
@Service
public class SimuFilesService {
    @Resource
    SimuMapper simuMapper;
    @Resource
    PropertiesConfig config;
    @Resource
    GedbService gedbService;
    @Resource
    UwService uwService;
    @Resource
    ResultService resultService;
    public IPage<SimuPo> get(SimuVo vo) {
        QueryWrapper<SimuPo> wrapper = getPageWrapper(vo);
        Page<SimuPo> page = new Page<>(vo.getPageIndex(), vo.getPageSize());
        page.addOrder(OrderItem.desc("id"));
        IPage<SimuPo> paged = simuMapper.selectPage(page, wrapper);
        return paged;
    }
    private QueryWrapper<SimuPo> getPageWrapper(SimuVo vo) {
        QueryWrapper<SimuPo> wrapper = new QueryWrapper<>();
        if (null != vo.getId()) {
            wrapper.eq("id", vo.getId());
        }
        if (null != vo.getPid()) {
            wrapper.eq("pid", vo.getPid());
        }
        if (null != vo.getNum()) {
            wrapper.eq("num", vo.getNum());
        }
        if (!StringHelper.isEmpty(vo.getName())) {
            wrapper.like("lower(name)", vo.getName().trim().toLowerCase());
        }
        if (!CollUtil.isEmpty(vo.getStatus())) {
            wrapper.in("status", vo.getStatus());
        }
        return wrapper;
    }
    private boolean delDir(String dir) {
        File file = new File(dir);
        if (!file.exists() || !file.isDirectory()) {
            return false;
        }
        return FileUtil.del(dir);
    }
    public boolean createByfiles(CreateSimuVo vo) {
        Date now = new Date();
        String date = StringHelper.YMDHMS2_FORMAT.format(now);
        if (StringHelper.isEmpty(vo.getName())) {
            vo.setName(date);
        }
        DataPo data = BeanUtil.copyProperties(vo, DataPo.class);
        data.setPath(date, date);
        initPath(data);
        SimuPo simu = new SimuPo(vo.getNum(), vo.getPid(), vo.getName(), JSONUtil.toJsonStr(data), 0, vo.getBak());
        simu.setServiceName(date);
        simu.setCreateTime(new Timestamp(now.getTime()));
        int rows = simuMapper.insert(simu);
        if (rows > 0) {
            asyncCall(simu);
        }
        return rows > 0;
    }
    private void initPath(DataPo data) {
        createDir(config.getInPath() + File.separator + data.getInPath());
        createDir(config.getOutPath() + File.separator + data.getOutPath());
    }
    private void createDir(String path) {
        File f = new File(path);
        if (f.exists() && f.isDirectory()) {
            FileUtil.del(f);
        }
        f.mkdirs();
    }
    private void asyncCall(SimuPo simu) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(new Runnable() {
            @Override
            @SneakyThrows
            public void run() {
                cope(simu);
            }
        });
        executor.shutdown();
    }
    /**
     * "状态:
     * 0-创建仿真任务,
     * 1-连接GEDB库,
     * 2-下载空间数据,
     * 3-下载高程数据,
     * 4-生成降雨文件,
     * 5-生成配置文件,
     * 6-模拟内涝仿真,
     * 7-处理水位文件,
     * 8-处理排水文件,
     * 9-处理仿真结果,
     * 10-完成,-10-出错
     *
     * @param simu æ¨¡æ‹Ÿ
     */
    private void cope(SimuPo simu) {
        try {
            DataPo data = JSONUtil.toBean(simu.getData(), DataPo.class);
            update(simu, 1, null);
            String token = gedbService.getToken();
            GeDb db = gedbService.connectGedb(token, data);
            simu.setData(JSONUtil.toJsonStr(data));
            update(simu, 2, null);
            gedbService.copeVectors(token, data, db);
            update(simu, 3, null);
            gedbService.copeDem(token, data);
            update(simu, 4, null);
            uwService.createRainFile(data);
            update(simu, 5, null);
            uwService.createConfig(data);
            update(simu, 6, null);
            uwService.callExe(data);
            update(simu, 7, null);
            //uwService.copeWaterFiles();
            update(simu, 8, null);
            uwService.copeDrainFiles(data);
            update(simu, 9, null);
            resultService.process(data);
            update(simu, 10, "完成");
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            update(simu, -simu.getStatus(), ex.getMessage());
        }
    }
    private void update(SimuPo simu, int status, String rs) {
        simu.setStatus(status);
        if (null != rs) simu.setResult(rs);
        simu.setUpdateTime(WebHelper.getCurrentTimestamp());
        simuMapper.updateById(simu);
    }
}
src/main/resources/application-prod.yml
@@ -104,8 +104,8 @@
  # æŸ¥è¯¢ä¸åŒæ•°æ®åº“类型下的数据地址
  queryUrl: http://106.120.22.26:8024/geo-service/entitydbdata/layer/query
# é¡¹ç›®æ¨¡æ‹Ÿæ–‡ä»¶ä¸Šä¼ å­˜æ”¾çš„位置
simu-file:
# æ¨¡æ‹Ÿé¡¹ç›®
simu-app:
  # é¡¹ç›®æ¨¡æ‹Ÿæ–‡ä»¶ä¸Šä¼ å­˜æ”¾çš„位置
  filePath: D:\simu\app\upload
src/main/resources/application-zyy.yml
@@ -102,10 +102,10 @@
  # æŸ¥è¯¢ä¸åŒæ•°æ®åº“类型下的数据地址
  queryUrl: http://106.120.22.26:8024/geo-service/entitydbdata/layer/query
# é¡¹ç›®æ¨¡æ‹Ÿæ–‡ä»¶ä¸Šä¼ å­˜æ”¾çš„位置
simu-file:
# æ¨¡æ‹Ÿé¡¹ç›®
simu-app:
  # é¡¹ç›®æ¨¡æ‹Ÿæ–‡ä»¶ä¸Šä¼ å­˜æ”¾çš„位置
  filePath: D:\simu\app\upload
  filePath: D:\simu\files
config:
  ver: 0.2