package com.fd.server.impl; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.fd.constant.Command; import com.fd.constant.MsgCode; import com.fd.constant.TypeCode; import com.fd.dto.ConfigJsonDto; import com.fd.dto.PageDto; import com.fd.dto.StyleDto; import com.fd.entity.FileEntity; import com.fd.entity.OutputFileEntity; import com.fd.entity.StyleEntity; import com.fd.entity.User; import com.fd.repository.FileRepository; import com.fd.repository.OutputFileRepository; import com.fd.repository.StyleRepository; import com.fd.repository.UserRepository; import com.fd.server.VectorServer; import com.fd.shiro.JWTUtil; import com.fd.util.CmdUtil; import com.fd.util.FileUtils; import com.fd.util.R; import com.fd.util.RegexUtils; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.math.BigDecimal; import java.util.*; /** * Created by Owen on 2019/11/21 0021 15:29 */ @Log4j2 @Service //@Transactional public class VectorServerImpl extends BaseServerImpl implements VectorServer { @Value("${input.file.path.vector}") private String INPUT_FILE_PATH; @Value("${output.file.path.vector}") private String OUTPUT_FILE_PATH; // @Value("${copy.file.path.vector}") // private String MOVE_FILE_TO_SERVER; // config.json 地址 @Value("${config.path}") private String CONFIG_JSON_PATH; // config.json teileset 的相对路径 // @Value("${config.tileset}") // private String CONFIG_TILESET; @Value("${base.path}") private String BASE_PATH; @Autowired private FileRepository fileRepository; @Autowired private OutputFileRepository outputFileRepository; @Autowired private StyleRepository styleRepository; @Autowired private UserRepository userRepository; @Override public R moveFileToServer(Long fileId, ConfigJsonDto param) { Optional o = outputFileRepository.findById(fileId); if (!o.isPresent()) { log.info("id:{} 不存在", fileId); return new R(50002, MsgCode.E50002); } OutputFileEntity entity = o.get(); // FileUtils.createDir(MOVE_FILE_TO_SERVER); try { // org.apache.commons.io.FileUtils.copyDirectoryToDirectory(new File(entity.getSlicePath()), new File(MOVE_FILE_TO_SERVER)); // 修改前端的config.json 文件 writeJsonFile(param, entity.getDirectory(), entity); //修改linux 文件权限 // String cmd = Command.CMD_CHOMD_755; // String slice = MOVE_FILE_TO_SERVER + entity.getDirectory(); // cmd = cmd.replace("@path", slice); // log.info("cmd: {}", cmd); // cmdServer.exeCmdInt(cmd); entity.setStatus(8); entity.setServicePath(entity.getSlicePath()); entity.setUpdateTime(new Date()); // 添加图层角色 entity.setLayerRole(param.getRole()); outputFileRepository.save(entity); return new R(200, MsgCode.SUCCESS); } catch (Exception e) { e.printStackTrace(); // 服务发布失败 entity.setStatus(10); entity.setUpdateTime(new Date()); outputFileRepository.save(entity); return new R(51004, MsgCode.E51004, e); } } @Override public R deleteById(Long fileId) { // 删除服务器文件 Optional e = outputFileRepository.findById(fileId); if (!e.isPresent()) { return new R(50002, MsgCode.E50002); } OutputFileEntity entity = e.get(); // 删除配置文件config.json制定行 StyleEntity styleEntity = styleRepository.findByOutputFileIdTop(fileId); if (styleEntity != null) { deleteRowConfigJson(styleEntity); } // 删除数据库记录 outputFileRepository.deleteById(fileId); fileRepository.deleteById(entity.getUploadId()); styleRepository.deleteByOutputFileId(fileId); // 删除文件 if (entity.getUploadPath() != null) { String path = entity.getUploadPath(); deleteFolder(path, entity); } if (entity.getUnZipPath() != null) { FileUtils.delFolder(entity.getUnZipPath()); } if (entity.getCoordGeneralPath() != null) { String path = entity.getCoordGeneralPath(); deleteFolder(path, entity); } if (entity.getCoordStrictPath() != null) { String path = entity.getCoordStrictPath(); deleteFolder(path, entity); } if (entity.getWfsPath() != null) { String path = entity.getWfsPath(); deleteFolder(path, entity); } // 文件类型 if (entity.getGeojsonPath() != null) { log.info("test file geojson"); String path = entity.getGeojsonPath(); deleteFolder(path, entity); } if (entity.getSlicePath() != null) { FileUtils.delFolder(entity.getSlicePath()); } return new R(200, MsgCode.SUCCESS); } // 以目录形式删除 private void deleteFolder(String path, OutputFileEntity entity) { String directory = entity.getDirectory(); int length = directory.length(); path = path.substring(0, path.lastIndexOf(directory) + length); log.warn("delete vector file: {}", path); FileUtils.delFolder(path); } @Override public R uploadDirectoryFileMul(MultipartFile[] files, String directoryName, String coord, String token) { log.warn("run uploadDirectoryFileMul"); // 判断目录重名 List en = fileRepository.findByDirectoryAndResStatus(directoryName, 0); if (en.size() > 0) { return new R(51007, MsgCode.E51007); } // 创建目录路径 String filePath = INPUT_FILE_PATH + directoryName + File.separator; FileUtils.createDir(filePath); FileEntity entity = new FileEntity(); StringBuilder sb = new StringBuilder(); // 检查文件名、格式 int suffixCheckInt = 0; HashSet setPrefix = new HashSet<>(); // 记录shp 信息 boolean shpFlag = false; String shpName = ""; if (files != null && files.length > 0) { for (MultipartFile f : files) { String filename = f.getOriginalFilename(); // 文件是否包含中文字符 if (RegexUtils.regexChinese(filename)) { return new R(51005, MsgCode.E51005); } log.info("fileName : {}", filename); String s = StringUtils.substringAfterLast(filename, "."); // 判断后缀名,需要包含这以下四个 String [] suffixCheck = {"dbf","shp","shx","prj"}; if (Arrays.asList(suffixCheck).contains(s)) { suffixCheckInt += 1; // 判断前缀名字是否一致 String prefix = StringUtils.substringBeforeLast(filename, "."); setPrefix.add(prefix); } if ("shp".equals(s)) { shpFlag = true; shpName = filename; } try { FileUtils.bigFileWrite(f.getInputStream(), filePath + filename); } catch (IOException e) { e.printStackTrace(); } sb.append(filename).append(","); } } // 上传文件名是否一致 if (setPrefix.size() > 1) { log.info("文件名前缀不一致"); return new R(51009, MsgCode.E51009); } // 上传文件格式有误 if (suffixCheckInt != 4) { log.info("文件后缀名有误"); return new R(51008, MsgCode.E51008); } String username = JWTUtil.getUsername(token); // 根据用户名查找用户 User user = userRepository.findByUsername(username); OutputFileEntity outputFile = new OutputFileEntity(); if (shpFlag) { entity.setDirectory(directoryName); entity.setFileName(sb.toString()); entity.setFileUrl(filePath + shpName); entity.setCreateTime(new Date()); entity.setUpdateTime(new Date()); entity.setType(TypeCode.FILE_TYPE_VECTOR); entity.setCoord(coord); entity.setResStatus(0); entity = fileRepository.save(entity); outputFile.setUploadId(entity.getId()); outputFile.setUploadPath(entity.getFileUrl()); outputFile.setDirectory(entity.getDirectory()); outputFile.setFileName(shpName); outputFile.setStatus(2); outputFile.setType(TypeCode.FILE_TYPE_VECTOR); outputFile.setCoord(entity.getCoord()); outputFile.setCreateTime(new Date()); outputFile.setUpdateTime(new Date()); outputFile.setResStatus(0); // 添加分组 outputFile.setUserId(user.getId()); outputFile.setUserGroup(user.getUserGroup()); outputFile = outputFileRepository.save(outputFile); } return new R(200, outputFile); } @Override public R findByType(String type, PageDto pageDto) { Page page = outputFileRepository.findByTypeAndResStatus(type, 0, PageRequest.of(pageDto.getPageNum(), pageDto.getPageSize(), Sort.by("createTime").descending())); return new R(200, page); } @Override public List findByDirectory(String directory) { return fileRepository.findByDirectoryAndResStatus(directory, 0); } @Override public FileEntity findByUploadId(Long uploadId) { Optional o = fileRepository.findById(uploadId); if (o.isPresent()) { return o.get(); } return null; } /** * 修改样式 * * @param entity * @return */ @Override public R editStyle(StyleDto entity) { StyleEntity styleEntity = styleRepository.findByOutputFileIdTop(entity.getOutputFileId()); Optional o = outputFileRepository.findById(entity.getOutputFileId()); OutputFileEntity outputFileEntity = null; if (o.isPresent()) { outputFileEntity = o.get(); outputFileEntity.setStatus(11); outputFileEntity.setUpdateTime(new Date()); outputFileRepository.save(outputFileEntity); } styleEntity.setUpdateTime(new Date()); styleEntity.setContent(entity.getContent()); StyleEntity save = styleRepository.save(styleEntity); /** * 发布完成才允许这一步操作,因为第一次发布时,还没有样式在config里面 * * 发布时数据,已经把样式提交过去config了 */ editStyleConfigJson(save); return new R(200, save.getOutputFileId()); } @Override public StyleEntity saveStyle(StyleEntity entity) { return styleRepository.save(entity); } @Override public R getStyle(Long id) { return new R(200, styleRepository.findByOutputFileIdTop(id)); } @Override public Map cmdJudgeCoord(String commandStr) { // 命令运行结果 1:失败, 0:成功 Integer isCmd = null; StringBuffer sb = new StringBuffer(); StringBuffer errorStr = new StringBuffer(); Map map = null; try { String[] cmd = new String[]{"/bin/sh", "-c", commandStr}; Process ps = Runtime.getRuntime().exec(cmd); BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream())); BufferedReader errorBuf = new BufferedReader(new InputStreamReader(ps.getErrorStream())); // error : 坑, 控制台信息是从errorBuf这里出来的 String errorLine; while ((errorLine = errorBuf.readLine()) != null) { errorStr.append(errorLine).append("\n"); } if (StringUtils.isNotEmpty(errorStr)) { log.info("error result: {}", errorStr.toString()); } // success ,没有获取到信息 String line; while ((line = br.readLine()) != null) { //执行结果加上回车 sb.append(line).append("\n"); // 获取经纬度 if (line.contains("Extent: (")) { log.info("extent: {}", line); map = getExtent(line); } } log.info("result: {}", sb.toString()); // 结束命令行 isCmd = ps.waitFor(); // 关闭流 br.close(); errorBuf.close(); } catch (Exception e) { e.printStackTrace(); } if (isCmd == 0) { log.info("end exeCmd : {}", isCmd); // 判断坐标 if (sb.toString().contains("GEOGCS[\"China Geodetic Coordinate System 2000\"")) { // 需要普通坐标转换 isCmd = 1000; map.put("code", isCmd); log.info("需要坐标转换code:{}, GEOGCS[\"China Geodetic Coordinate System 2000\"", isCmd); } if (sb.toString().contains("GEOGCS[\"Xian 1980\"")) { // 需要严格坐标转换 isCmd = 1001; map.put("code", isCmd); log.info("需要严格坐标转换code:{}, GEOGCS[\"Xian 1980\"", isCmd); } if (sb.toString().contains("GEOGCS[\"WGS 84\"")) { // 不需要坐标转换 isCmd = 0; map.put("code", isCmd); log.info("不需要坐标转换code:{}, GEOGCS[\"WGS 84\"", isCmd); } } else { map.put("code", isCmd); log.info("error exeCmd wsitFore: {}", isCmd); } return map; } /** * 这个进度输出是从getErrorStream 输出 * @param commandStr * @param entity * @return */ @Override public Integer cmdSlice(String commandStr, OutputFileEntity entity) { log.info("run vector cmdSlice"); // 命令运行结果 1:失败, 0:成功 Integer isCmd = null; try { String[] cmd = new String[]{"/bin/sh", "-c", commandStr}; Process ps = Runtime.getRuntime().exec(cmd); BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream())); BufferedReader errorBuf = new BufferedReader(new InputStreamReader(ps.getErrorStream())); StringBuffer sb = new StringBuffer(); StringBuffer errorStr = new StringBuffer(); // error : 坑, 控制台信息是从errorBuf这里出来的 String errorLine; while ((errorLine = errorBuf.readLine()) != null) { errorStr.append(errorLine).append("\n"); log.info("error: {}", errorLine); // 获取进度 if (errorLine.contains("%")) { String s = StringUtils.substringBefore(errorLine, "%"); // 去除空白字符串 s = StringUtils.deleteWhitespace(s); // 只有是数字的 if (RegexUtils.regexInt(s)) { Integer round = (int) Math.round(Double.valueOf(s)); // log.info("round: {}", round); if (round % 5 == 0 ) { // log.info("round1: {}", round); entity.setUpdateTime(new Date()); entity.setProgress(round - 1); if (s.equals("99.9")) { entity.setProgress(100); } outputFileRepository.save(entity); } } } } if (StringUtils.isNotEmpty(errorStr)){ log.info("error result: {}", errorStr.toString()); } // success ,没有获取到信息 String line; while ((line = br.readLine()) != null) { //执行结果加上回车 sb.append(line).append("\n"); log.info("data: {}", line); } log.info("result: {}", sb.toString()); // 结束命令行 isCmd = ps.waitFor(); // 关闭流 br.close(); errorBuf.close(); } catch (Exception e) { e.printStackTrace(); } if (isCmd == 0) { log.info("end exeCmd : {}", isCmd); } else { log.info("wsitFore cmd run error : {}", isCmd); } return isCmd; } @Override public FileEntity findByInputFileId(Long fileId) { Optional o = fileRepository.findById(fileId); if (o.isPresent()){ FileEntity fileEntity = o.get(); return fileEntity; } return null; } @Override public FileEntity saveInputFile(FileEntity fileEntity) { FileEntity save = fileRepository.save(fileEntity); return save; } @Override public Integer exeCmd(String cmd) { Integer isCmd = exeCmdSingle(cmd); return isCmd; } private Integer exeCmdSingle(String commandStr) { // 命令运行结果 1:失败, 0:成功 Integer isCmd = null; try { String[] cmd = new String[]{"/bin/sh", "-c", commandStr}; Process ps = Runtime.getRuntime().exec(cmd); BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream())); BufferedReader errorBuf = new BufferedReader(new InputStreamReader(ps.getErrorStream())); StringBuffer sb = new StringBuffer(); StringBuffer errorStr = new StringBuffer(); // error : 坑, 控制台信息是从errorBuf这里出来的 String errorLine; while ((errorLine = errorBuf.readLine()) != null) { errorStr.append(errorLine).append("\n"); } if (StringUtils.isNotEmpty(errorStr)){ log.info("error result: {}", errorStr.toString()); } // success ,没有获取到信息 String line; while ((line = br.readLine()) != null) { //执行结果加上回车 sb.append(line).append("\n"); } log.info("result: {}", sb.toString()); // 结束命令行 isCmd = ps.waitFor(); // 关闭流 br.close(); errorBuf.close(); } catch (Exception e) { e.printStackTrace(); } if (isCmd == 0) { log.info("end exeCmd : {}", isCmd); } else { log.info("wsitFore cmd run error : {}", isCmd); } return isCmd; } /** * 获取经纬度平均值 * * @param str 传入参数 * @return map */ private Map getExtent(String str) { str = str.replace("Extent: (", ""); str = str.replaceAll("\\(", ""); str = str.replaceAll("\\)", ""); str = str.replaceAll(" -", ","); // 去除所有空白字符 str = StringUtils.deleteWhitespace(str); String[] strArray = str.split(","); List list = Arrays.asList(strArray); log.info("extent list: {}", Arrays.asList(strArray)); BigDecimal b0 = new BigDecimal(list.get(0)); BigDecimal b1 = new BigDecimal(list.get(1)); BigDecimal b2 = new BigDecimal(list.get(2)); BigDecimal b3 = new BigDecimal(list.get(3)); // 经度 BigDecimal longitude = b0.add(b2); longitude = longitude.divide(new BigDecimal(2), 6, BigDecimal.ROUND_HALF_UP); // 纬度 BigDecimal latitude = b1.add(b3); latitude = latitude.divide(new BigDecimal(2), 6, BigDecimal.ROUND_HALF_UP); HashMap map = new HashMap<>(); map.put("longitude", longitude); map.put("latitude", latitude); return map; } @Override public OutputFileEntity findById(Long fileId) { Optional o = outputFileRepository.findById(fileId); if (o.isPresent()) { return o.get(); } return null; } @Override public OutputFileEntity save(OutputFileEntity fileSchedule) { return outputFileRepository.save(fileSchedule); } private void writeJsonFile(ConfigJsonDto param, String lastName, OutputFileEntity entity) { StyleEntity styleEntity = styleRepository.findByOutputFileIdTop(entity.getId()); String s = FileUtils.readFile(CONFIG_JSON_PATH); JSONObject original = JSON.parseObject(s); log.info("original: {}", s); JSONArray layers = JSON.parseArray(original.getString("layers")); JSONObject subJson = new JSONObject(); long cu = System.currentTimeMillis(); String name = "vector_" + cu; // 新增id字段,为要素查询使用 subJson.put("id", entity.getId()); // 需要唯一 subJson.put("name", name); subJson.put("text", param.getText()); // vector 就用这个类型geodata subJson.put("type", "geodata"); subJson.put("checked", false); subJson.put("show", true); // subJson.put("url", "../data/" + lastName); String slicePath = entity.getSlicePath(); // slicePath = slicePath.replace("/root/gis/data", ""); slicePath = slicePath.replace(BASE_PATH, ""); subJson.put("url", slicePath); layers.add(subJson); original.put("layers", layers); log.info("original update: {}", original.toJSONString()); try { FileUtils.fileWriter(JSON.toJSONString(original), CONFIG_JSON_PATH); // 将图层信息保存到db // 前端需要layer信息 styleEntity.setLayer(subJson.toJSONString()); styleEntity.setUpdateTime(new Date()); styleEntity.setName(name); styleRepository.save(styleEntity); } catch (IOException e) { e.printStackTrace(); } } /** * 删除指定行的config.json 数据 */ private void deleteRowConfigJson(StyleEntity entity) { String s = FileUtils.readFile(CONFIG_JSON_PATH); JSONObject original = JSON.parseObject(s); log.info("original: {}", s); JSONArray layers = JSON.parseArray(original.getString("layers")); for (int i = 0; i < layers.size(); i++) { JSONObject o = (JSONObject) layers.get(i); if (o.getString("name").equals(entity.getName())) { // 删除对象 layers.remove(i); } } // 更新json original.put("layers", layers); log.info("original update: {}", original.toJSONString()); // 更新config.json try { FileUtils.fileWriter(JSON.toJSONString(original), CONFIG_JSON_PATH); } catch (IOException e) { e.printStackTrace(); } } /** * 编辑样式,指定行的config.json 数据 * 添加样式 */ private void editStyleConfigJson(StyleEntity entity) { String s = FileUtils.readFile(CONFIG_JSON_PATH); JSONObject original = JSON.parseObject(s); log.info("original: {}", s); JSONArray layers = JSON.parseArray(original.getString("layers")); for (int i = 0; i < layers.size(); i++) { JSONObject o = (JSONObject) layers.get(i); if (o.getString("name").equals(entity.getName())) { log.warn("old sytle: {}", o.toJSONString()); //修改样式 o.put("style", JSON.parse(entity.getContent())); } } log.warn("update sytle: {}", layers.toJSONString()); // 更新json original.put("layers", layers); log.info("original update: {}", original.toJSONString()); // 更新config.json try { FileUtils.fileWriter(JSON.toJSONString(original), CONFIG_JSON_PATH); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException { String inPath = "F:\\test\\clip\\aaa\\wwww"; String outPath = "F:\\test\\copy\\aaa\\123.com"; System.out.println(inPath.substring(0, inPath.lastIndexOf("aaa") + 3)); System.out.println(outPath.substring(0, outPath.lastIndexOf("aaa") + 3)); } }