package com.fd.server.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.fd.constant.MsgCode; import com.fd.constant.TypeCode; import com.fd.dto.ConfigJsonDto; import com.fd.dto.PageDto; import com.fd.entity.FileEntity; //import com.fd.entity.LayerEntity; import com.fd.entity.OutputFileEntity; import com.fd.entity.StyleEntity; import com.fd.entity.User; import com.fd.repository.FileRepository; //import com.fd.repository.LayerRepository; import com.fd.repository.OutputFileRepository; import com.fd.repository.StyleRepository; import com.fd.repository.UserRepository; import com.fd.server.CmdServer; import com.fd.server.RasterServer; import com.fd.shiro.JWTUtil; import com.fd.util.FileUtils; import com.fd.util.R; 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.IOException; import java.io.InputStreamReader; import java.util.Date; import java.util.List; import java.util.Optional; /** * Created by Owen on 2019/11/21 0021 15:29 */ @Log4j2 @Service public class RasterServerImpl extends BaseServerImpl implements RasterServer { @Value("${input.file.path.raster}") private String INPUT_FILE_PATH; @Value("${output.file.path.raster}") private String OUTPUT_FILE_PATH; // @Value("${copy.file.path.raster}") // 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 CmdServer cmdServer; @Autowired private StyleRepository styleRepository; @Autowired private UserRepository userRepository; @Override public R deleteById(Long fileId) { // 删除服务器文件 // 删除服务器文件 Optional e = outputFileRepository.findById(fileId); if (!e.isPresent()) { return new R(50002, MsgCode.E50002); } OutputFileEntity fileEntity = e.get(); // 删除配置文件config.json制定行 StyleEntity styleEntity = styleRepository.findByOutputFileIdTop(fileId); if (styleEntity != null) { deleteRowConfigJson(styleEntity); } // 删除数据库记录 outputFileRepository.deleteById(fileId); fileRepository.deleteById(fileEntity.getUploadId()); styleRepository.deleteByOutputFileId(fileId); // 文件 if (fileEntity.getUploadPath() != null) { FileUtils.delFolder(fileEntity.getUploadPath()); } if (fileEntity.getCoordGeneralPath() != null) { FileUtils.delFolder(fileEntity.getCoordGeneralPath()); } if (fileEntity.getUnZipPath() != null) { FileUtils.delFolder(fileEntity.getUnZipPath()); } if (fileEntity.getGeojsonPath() != null) { FileUtils.delFolder(fileEntity.getGeojsonPath()); } if (fileEntity.getCoordStrictPath() != null) { FileUtils.delFolder(fileEntity.getCoordStrictPath()); } if (fileEntity.getSlicePath() != null) { FileUtils.delFolder(fileEntity.getSlicePath()); } return new R(200, MsgCode.SUCCESS); } /** * 删除指定行的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(); } } @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(); try { // 修改前端的config.json 文件 String lastName = StringUtils.substringAfterLast(entity.getSlicePath(), "/"); log.info("lastName: {}", lastName); writeJsonFile(param, lastName, entity); // 成功,更新状态 entity.setStatus(8); entity.setUpdateTime(new Date()); // 添加图层角色 entity.setLayerRole(param.getRole()); outputFileRepository.save(entity); return new R(200, MsgCode.SUCCESS); } catch (Exception e) { entity.setStatus(10); entity.setUpdateTime(new Date()); outputFileRepository.save(entity); e.printStackTrace(); return new R(51004, MsgCode.E51004, e); } } @Override public R uploadBigFile(MultipartFile file, String strCoord, String token) { long start = System.currentTimeMillis(); if (file.isEmpty() || file.getSize() <= 0) { log.info("文件为空"); return new R(50001, MsgCode.E50001); } // 文件名全名 String fullFileName = file.getOriginalFilename(); // 创建目录路径 FileUtils.createDir(INPUT_FILE_PATH); // 拼接唯一文件名 long timeMillis = System.currentTimeMillis(); // String fileName = timeMillis + "_" + fullFileName; String fileName = fullFileName; // 文件保存路径 String filePath = INPUT_FILE_PATH + fileName; // 写文件到本地 try { FileUtils.bigFileWrite(file.getInputStream(), filePath); } catch (IOException e) { e.printStackTrace(); } log.info("filePath: {}", filePath); String username = JWTUtil.getUsername(token); // 根据用户名查找用户 User user = userRepository.findByUsername(username); // 保存信息到db FileEntity entity = new FileEntity(); entity.setFileName(fileName); entity.setFileUrl(filePath); entity.setCreateTime(new Date()); entity.setUpdateTime(new Date()); entity.setType(TypeCode.FILE_TYPE_RASTER); entity.setCoord(strCoord); entity.setStatus(2); entity.setResStatus(0); fileRepository.save(entity); OutputFileEntity outputFile = new OutputFileEntity(); outputFile.setUploadId(entity.getId()); outputFile.setUploadPath(entity.getFileUrl()); outputFile.setFileName(entity.getFileName()); outputFile.setStatus(2); outputFile.setResStatus(0); outputFile.setCoord(strCoord); outputFile.setType(TypeCode.FILE_TYPE_RASTER); outputFile.setCreateTime(new Date()); outputFile.setUpdateTime(new Date()); // 添加分组 outputFile.setUserId(user.getId()); outputFile.setUserGroup(user.getUserGroup()); outputFile = outputFileRepository.save(outputFile); long end = System.currentTimeMillis(); log.info("end uploadBigFile, total time: {} s", (end - start)/1000); return new R(200, outputFile); } @Override public R findByType(String fileTypeRaster, PageDto pageDto) { Page page = outputFileRepository.findByTypeAndResStatus(fileTypeRaster, 0, PageRequest.of(pageDto.getPageNum(), pageDto.getPageSize(), Sort.by("createTime").descending())); return new R(200, page); } @Override public OutputFileEntity findById(Long fileId) { Optional o = outputFileRepository.findById(fileId); if (o.isPresent()) { return o.get(); } return null; } @Override public List findByFileName(String fileName) { return fileRepository.findByFileNameAndTypeAndResStatus(fileName, TypeCode.FILE_TYPE_RASTER, 0); } @Override public OutputFileEntity save(OutputFileEntity fileSchedule) { return outputFileRepository.save(fileSchedule); } @Override public FileEntity findByInputFileId(Long fileId) { Optional o = fileRepository.findById(fileId); if (o.isPresent()) { return o.get(); } return null; } @Override public FileEntity saveInputFile(FileEntity fileEntity) { return fileRepository.save(fileEntity); } @Override public Integer cmdJudgeCoord(String commandStr) { // 命令运行结果 1:失败, 0:成功 Integer isCmd = null; StringBuffer sb = new StringBuffer(); StringBuffer errorStr = new StringBuffer(); 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) { // log.info("===== br.readLine: ======== {}", br.readLine()); //执行结果加上回车 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); // 判断坐标 if (sb.toString().contains("+proj=tmerc +lat_0=0 +lon_0=114 +k=1 +x_0=38500000")) { // 需要坐标转换 // 1000: 需要转换 isCmd = 1000; } if (sb.toString().contains("+proj=longlat +datum=WGS84")) { // 不需要坐标转换 isCmd = 0; } } else { log.info("error cmd wsitFore: {}", isCmd); } return isCmd; } @Override public Integer exeCmd(String cmd1, String cmd2) { exeCmdSingle(cmd1); Integer isCmd = exeCmdSingle(cmd2); return isCmd; } @Override public Integer cmdSlice(String commandStr, OutputFileEntity entity) { log.warn("run cmdSlice"); Integer isCmd = null; // 命令运行结果 1:失败, 0:成功 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(); // 进度 int pre = 0; int num; String str; while ((num = br.read()) != -1) { str = String.valueOf((char) num); // 判断数字 if (numRegex(str)) { if (!str.equals("0")) { // 非0开头的 sb.append(",").append(str); } else { // 以0开头的 sb.append(str); } // 截取进度数字 str = StringUtils.substringAfterLast(sb.toString(), ","); // 100,1000都会当一次 if (str.length() == 2) { pre = pre + 5; log.warn("pre: {}", pre); // 能被2整除的存一下db if (pre % 2 == 0) { entity.setProgress(pre); entity.setUpdateTime(new Date()); outputFileRepository.save(entity); } } } } log.info("cmd console: {}", sb.toString()); StringBuffer errorStr = new StringBuffer(); String errorLine; while ((errorLine = errorBuf.readLine()) != null) { errorStr.append(errorLine).append("\n"); } if (StringUtils.isNotEmpty(errorStr)){ log.info("error result: {}", errorStr.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); } log.warn("end exeCmdRasterSlice"); 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; } private void writeJsonFile(ConfigJsonDto param, String lastName, OutputFileEntity entity) { String s = FileUtils.readFile(CONFIG_JSON_PATH); StyleEntity styleEntity = styleRepository.findByOutputFileIdTop(entity.getId()); if (styleEntity == null) { styleEntity = new StyleEntity(); styleEntity.setOutputFileId(entity.getId()); styleEntity.setCreateTime(new Date()); styleEntity.setResStatus(0); } 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 = "raster_" + cu; subJson.put("name", name); subJson.put("text", param.getText()); // raster 就用这个类型 subJson.put("type", "imagery"); subJson.put("checked", false); subJson.put("show", true); 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(); } } // 匹配数字 private boolean numRegex(String str) { String reg = "\\d"; if (StringUtils.isEmpty(str)) { return false; } return str.matches(reg); } }