package com.fdkankan.fusion.down; import cn.hutool.core.io.FileUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.deepoove.poi.XWPFTemplate; import com.fdkankan.fusion.common.FilePath; import com.fdkankan.fusion.common.ResultData; import com.fdkankan.fusion.common.util.ShellUtil; import com.fdkankan.fusion.common.util.UploadToOssUtil; import com.fdkankan.fusion.entity.*; import com.fdkankan.fusion.httpClient.LaserService; import com.fdkankan.fusion.httpClient.response.FdkkResponse; import com.fdkankan.fusion.request.CaseParam; import com.fdkankan.fusion.response.DownVo; import com.fdkankan.fusion.response.DownloadProcessVo; import com.fdkankan.fusion.response.FusionNumVo; import com.fdkankan.fusion.response.SceneVo; import com.fdkankan.fusion.service.*; import com.fdkankan.fusion.service.impl.DownService; import com.fdkankan.redis.util.RedisUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.io.File; import java.io.FileOutputStream; import java.nio.charset.StandardCharsets; import java.util.HashSet; import java.util.List; @Service @Slf4j public class CaseDownService { @Value("${server.servlet.context-path}") String basePath; public static String jsonDataName = "data.json"; public static String caseInfo = "/case/getInfo?caseId="; public static String caseSettingsInfo = "/caseSettings/info?caseId="; public static String hostIcon = "/edit/hotIcon/list?caseId="; public static String caseView = "/caseView/allList?caseId="; public static String caseFiles = "/caseFiles/allList?caseId="; public static String caseFilesType = "/caseFilesType/allList?caseId="; public static String caseScene = "/case/sceneList?caseId="; public static String caseFusion = "/caseFusion/list?caseId="; public static String caseVideoFolder = "/caseVideoFolder/allList?caseId="; public static String caseVideo = "/caseVideo/allList?folderId="; public static String caseTag = "/caseTag/allList?caseId="; public static String caseTagPoint = "/caseTagPoint/allList?tagId="; public static String caseInquest = "/caseInquest/info?caseId="; public static String caseExtractDetail = "/caseExtractDetail/info?caseId="; public static String fusionGuide = "/fusionGuide/allList?caseId="; public static String fusionGuidePath = "/fusionGuidePath/allList?guideId="; public static String fusionMeter = "/fusionMeter/allList?fusionId="; public static String model = "/model/getInfo?modelId="; public static String caseImg = "/caseImg/getFfmpegImage?caseId="; public static String inquestInfoUrl = "/caseInquestInfo/info?caseId="; public static String casePathInfoUrl = "/casePath/info?caseId="; public static String caseAnimationUrl = "/caseAnimation/list?caseId="; public static String laserData = "/laser/dataset/%s/getDataSet"; public static String laserDataQuery = "/laser/filter/%s/query?datasetId=%s"; @Autowired ICaseService caseService; @Autowired ICaseSettingsService caseSettingsService; @Autowired IFusionNumService fusionNumService; @Autowired ICaseViewService caseViewService; @Autowired ICaseVideoFolderService caseVideoFolderService; @Autowired ICaseVideoService caseVideoService; @Autowired ICaseFilesService caseFilesService; @Autowired ICaseFilesTypeService caseFilesTypeService; @Autowired IHotIconService hotIconService; @Autowired ICaseTagService caseTagService; @Autowired ICaseTagPointService caseTagPointService; @Autowired IFusionGuideService fusionGuideService; @Autowired IFusionGuidePathService fusionGuidePathService; @Autowired ICaseInquestService caseInquestService; @Autowired ICaseExtractDetailService caseExtractDetailService; @Autowired IFusionMeterService fusionMeterService; @Autowired IModelService modelService; @Autowired LaserService laserService; @Autowired ICaseOfflineService caseOfflineService; @Autowired ICaseImgService caseImgService; @Autowired ICaseInquestInfoService caseInquestInfoService; @Autowired ICasePathService casePathService; @Autowired ICaseAnimationService animationService; @Autowired RedisUtil redisUtil; @Value("${spring.profiles.active}") private String environment; public static String downProcessKey = "fusion:down:offline:process:caseId:%s"; public DownVo checkDown(Integer caseId) { DownVo downVo = new DownVo(); String redisKey = String.format(downProcessKey, caseId); if( redisUtil.hasKey(redisKey)){ String res = redisUtil.get(redisKey); DownloadProcessVo downloadProcessVo = JSONObject.parseObject(res, DownloadProcessVo.class); if(downloadProcessVo.getStatus() == 1000 && downloadProcessVo.getPercent() == 100 && StringUtils.isNotBlank(downloadProcessVo.getUrl())){ downVo.setDownloadStatus(3); downVo.setDownloadUrl(downloadProcessVo.getUrl()); } } return downVo; } public void cleckDownUrl(Integer caseId) { String redisKey = String.format(downProcessKey, caseId); if( redisUtil.hasKey(redisKey)){ String res = redisUtil.get(redisKey); DownloadProcessVo downloadProcessVo = JSONObject.parseObject(res, DownloadProcessVo.class); if(downloadProcessVo.getStatus() == 1000 && downloadProcessVo.getPercent() == 100 && StringUtils.isNotBlank(downloadProcessVo.getUrl())){ redisUtil.del(redisKey); } } } @Async public void downOffline(Integer caseId){ try { String redisKey = String.format(downProcessKey, caseId); if( redisUtil.hasKey(redisKey)){ String res = redisUtil.get(redisKey); DownloadProcessVo downloadProcessVo = JSONObject.parseObject(res, DownloadProcessVo.class); if(downloadProcessVo.getStatus() != 1003 && (downloadProcessVo.getPercent()== null || downloadProcessVo.getPercent() != 100)){ return; } } setRedisProcess(caseId,0); //复制前端资源 cpIndexHtml(caseId); setRedisProcess(caseId,10); //创建data.json并下载资源 createDataJson(caseId); setRedisProcess(caseId,50); //打包zip String path = "/mnt/fusion/offline"; String name = "offline_"+ caseId; String zipName = path+File.separator+name+".zip"; ShellUtil.zipOffline(zipName,name); setRedisProcess(caseId,70); //上传oss String ossUrl = zipName.replace("/mnt/", ""); ShellUtil.yunUpload(zipName,ossUrl); Thread.sleep(2000L); FileUtil.del(zipName); ossUrl = queryPath + ossUrl; caseOfflineService.saveByCase(caseId,ossUrl); setRedisProcess(caseId,100,ossUrl); }catch (Exception e){ log.info("down-offline-error:{}",caseId,e); setRedisProcess(caseId,0,null,1003); } } public void setRedisProcess(Integer caseId,Integer num){ setRedisProcess(caseId,num,null,1000); } public void setRedisProcess(Integer caseId,Integer num,String url){ setRedisProcess(caseId,num,url,1000); } public void setRedisProcess(Integer caseId,Integer num,String url,Integer status){ String redisKey = String.format(downProcessKey, caseId); log.info("down-offline-process:{},{},{}",caseId,num,url); DownloadProcessVo processVo = new DownloadProcessVo(); processVo.setStatus(status); processVo.setPercent(num); processVo.setUrl( url); redisUtil.set(redisKey,JSONObject.toJSONString(processVo)); } public DownloadProcessVo process(Integer caseId) { DownloadProcessVo downVo = new DownloadProcessVo(); String redisKey = String.format(downProcessKey, caseId); if(redisUtil.hasKey(redisKey)){ return JSONObject.parseObject(redisUtil.get(redisKey),DownloadProcessVo.class); } return downVo; } public void createDataJson(Integer caseId){ log.info("down-offline-createDataJson:{}",caseId); JSONObject jsonObject = new JSONObject(); CaseParam param = new CaseParam(); param.setCaseId(caseId); //设置案件信息 jsonObject.put(basePath+inquestInfoUrl+caseId, ResultData.ok(caseInquestInfoService.getByCaseId(caseId))); jsonObject.put(basePath+caseInfo+caseId, ResultData.ok(caseService.getInfo(caseId))); List caseSettings = caseSettingsService.getByCaseId(caseId); jsonObject.put(basePath+caseSettingsInfo+caseId, ResultData.ok(caseSettings)); for (CaseSettings caseSetting : caseSettings) { downResource(caseId,caseSetting.getBack()); downResource(caseId,caseSetting.getCover()); } List listByCaseId = fusionNumService.getListByCaseId(caseId,null); jsonObject.put(basePath+caseFusion+caseId, ResultData.ok(listByCaseId)); for (FusionNumVo fusion : listByCaseId) { jsonObject.put(basePath+fusionMeter+fusion.getFusionId(), ResultData.ok(fusionMeterService.getListByFusionId(fusion.getFusionId(),null))); } for (FusionNumVo fusionNumVo : listByCaseId) { //下载媒体库模型 if(fusionNumVo.getSceneData() != null){ if(fusionNumVo.getSceneData().getType() ==3 && StringUtils.isNotBlank(fusionNumVo.getSceneData().getModelGlbUrl()) ){ downModel(caseId,fusionNumVo.getSceneData().getModelGlbUrl()); } } } List sceneVos = caseService.sceneList(param); for (SceneVo sceneData : sceneVos) { //下载模型 if(StringUtils.isNotBlank(sceneData.getModelGlbUrl())){ downModel(caseId,sceneData.getModelGlbUrl()); } if(sceneData.getType() != 3){ //下载场景离线包 downSwkk(caseId,sceneData.getNum(),sceneData.getType()); } if(sceneData.getType() == 2 || sceneData.getType() == 5){ FdkkResponse sceneInfo = laserService.getSceneInfo(sceneData.getNum()); HashSet dataSetIds = new HashSet<>(); if(sceneInfo != null){ JSONArray jsonArray = JSONArray.parseArray(JSONArray.toJSONString(sceneInfo.getData())); JSONArray newJsonArray = new JSONArray(); for (Object object : jsonArray) { JSONObject sceneInfoObj = (JSONObject) object; String newPath = String.format(FilePath.OFFLINE_LASER_OSS_PATH, sceneData.getNum(), sceneData.getNum()); String oldPath = sceneInfoObj.getString("webBin"); sceneInfoObj.put("oldWebBin",oldPath); sceneInfoObj.put("webBin",newPath + oldPath); newJsonArray.add(sceneInfoObj); dataSetIds.add( sceneInfoObj.getString("id")); } sceneInfo.setData(newJsonArray); jsonObject.put(String.format(laserData,sceneData.getNum()),sceneInfo); if(!dataSetIds.isEmpty()){ for (String dataSetId : dataSetIds) { FdkkResponse sceneInfo2 = laserService.getSceneInfoQuery(sceneData.getNum(),dataSetId); jsonObject.put(String.format(laserDataQuery,sceneData.getNum(),dataSetId),sceneInfo2); } } } } if(sceneData.getModelId() != null){ jsonObject.put(basePath+model+sceneData.getModelId(), ResultData.ok(modelService.getInfo(sceneData.getModelId()))); } } jsonObject.put(basePath+caseScene+caseId, ResultData.ok(sceneVos)); List caseViews = caseViewService.allList(caseId, null, null, null, null); jsonObject.put(basePath+caseView+caseId, ResultData.ok(caseViews)); for (CaseView view : caseViews) { downResource(caseId,view.getViewImg()); downResource(caseId,view.getViewImgSmall()); } List videoFolders = caseVideoFolderService.getAllList(caseId); jsonObject.put(basePath+caseVideoFolder+caseId, ResultData.ok(videoFolders)); for (CaseVideoFolder videoFolder : videoFolders) { downResource(caseId,videoFolder.getVideoFolderCover()); downResource(caseId,videoFolder.getVideoMergeUrl()); List allList = caseVideoService.getAllList(videoFolder.getVideoFolderId()); for (CaseVideo video : allList) { downResource(caseId,video.getVideoCover()); downResource(caseId,video.getVideoPath()); } jsonObject.put(basePath+caseVideo+videoFolder.getVideoFolderId(), ResultData.ok(allList)); } List caseFilesList = caseFilesService.allList(caseId, null); for (CaseFiles files : caseFilesList) { downResource(caseId,files.getFilesUrl()); } jsonObject.put(basePath+caseFiles+caseId, ResultData.ok(caseFilesList)); jsonObject.put(basePath+caseFilesType+caseId, ResultData.ok(caseFilesTypeService.list())); List hotIconList = hotIconService.getListByCaseId(caseId); for (HotIcon hotIcon : hotIconList) { downResource(caseId,hotIcon.getIconUrl()); } jsonObject.put(basePath+hostIcon+caseId, ResultData.ok(hotIconList)); List caseTagList = caseTagService.allList(caseId, null); jsonObject.put(basePath+caseTag+caseId, ResultData.ok(caseTagList)); for (CaseTag tag : caseTagList) { jsonObject.put(basePath+caseTagPoint+tag.getTagId(), ResultData.ok(caseTagPointService.allList(tag.getTagId()))); downResources(caseId,tag.getTagImgUrl()); downResource(caseId,tag.getHotIconUrl()); } jsonObject.put(basePath+casePathInfoUrl+caseId, ResultData.ok(casePathService.getByCaseId(caseId))); List fusionGuides = fusionGuideService.getAllList(caseId); jsonObject.put(basePath+fusionGuide+caseId, ResultData.ok(fusionGuides)); for (FusionGuide guide : fusionGuides) { downResource(caseId,guide.getCover()); List listByGuideId = fusionGuidePathService.getListByGuideId(guide.getFusionGuideId()); for (FusionGuidePath guidePath : listByGuideId) { downResource(caseId,guidePath.getCover()); } jsonObject.put(basePath+fusionGuidePath+guide.getFusionGuideId(), ResultData.ok(listByGuideId)); } CaseInquest caseInquest1 = caseInquestService.getByCaseId(caseId); if(caseInquest1 != null){ XWPFTemplate inquestTemp = caseInquestService.getWordByTemplate(caseInquest1); downWordByTemplate(caseId,inquestTemp,"caseInquest.doc"); } jsonObject.put(basePath+caseInquest+caseId, ResultData.ok(caseInquest1)); CaseExtractDetail caseExtractDetail1 = caseExtractDetailService.getByCaseId(caseId); if(caseExtractDetail1 != null){ XWPFTemplate detailTemp = caseExtractDetailService.getWordByTemplate(caseExtractDetail1); downWordByTemplate(caseId,detailTemp,"caseExtractDetail.doc"); } jsonObject.put(basePath+caseExtractDetail+caseId, ResultData.ok(caseExtractDetail1)); List caseImgList = caseImgService.getByCaseId(caseId, 1); for (CaseImg img : caseImgList) { downResource(img.getCaseId(),img.getImgUrl()); } jsonObject.put(basePath+caseImg+caseId, ResultData.ok(caseImgList)); jsonObject.put(basePath+caseAnimationUrl+caseId, ResultData.ok(animationService.getListByCaseId(caseId))); FileUtil.writeString(JSON.toJSONString(jsonObject), FilePath.OFFLINE_PACKAGE_PATH+caseId+"/www/package/"+jsonDataName,"UTF-8"); } //http://127.0.0.1:8080/offline.html?caseId=362&app=1&share=1#/show/summary static String batName = "start-browser.bat"; public void cpIndexHtml(Integer caseId){ log.info("down-offline-cpIndexHtml:{}",caseId); String caseOfflinePath = FilePath.OFFLINE_PACKAGE_PATH+caseId; FileUtil.copyContent(new File(FilePath.OFFLINE_TEMPLATE_PATH),new File(caseOfflinePath),true); String s = FileUtil.readString(caseOfflinePath + File.separator + batName, StandardCharsets.UTF_8); String s1 = s.replaceAll("@caseId", String.valueOf(caseId)); FileUtil.writeString(s1, caseOfflinePath + File.separator + batName,"UTF-8"); } @Autowired DownService downService; @Autowired UploadToOssUtil uploadToOssUtil; public void downSwkk(Integer caseId,String num,Integer type){ String swkkPath = FilePath.OFFLINE_PACKAGE_PATH+caseId + "/www/swkk/"+num; String swkkZipPath = swkkPath +".zip"; String swssPath = FilePath.OFFLINE_PACKAGE_PATH+caseId + "/www/swss/"+num; String swssZipPath = swssPath +".zip"; Integer isObj = 0; if(type == 4 || type == 6){ isObj =1; } try { DownVo downVo = downService.checkDownLoad(num, isObj,"offline"); log.info("down:{}",downVo); if(downVo.getDownloadStatus() == 3 && StringUtils.isNotBlank(downVo.getDownloadUrl())){ downZip(type,downVo.getDownloadUrl(),swkkZipPath,swkkPath,swssZipPath,swssPath); }else { DownVo down = downService.down(num, isObj,"offline"); if(down.getDownloadStatus() == 1){ DownloadProcessVo downloadProcessVo = downService.downloadProcess(num, isObj); while (downloadProcessVo.getStatus() != 1002 ){ downloadProcessVo = downService.downloadProcess(num, isObj); Thread.sleep(2000L); } downZip(type,downloadProcessVo.getUrl(),swkkZipPath,swkkPath,swssZipPath,swssPath); } } }catch (Exception e){ log.info("下载场景离线包失败:{}",num,e); } } @Value("${upload.query-path}") private String queryPath; public void downZip(Integer type ,String uri,String kkzipPath,String kknumPath,String sszipPath,String ssNumPath){ try { if(type != 2 && type != 5){ //深时点云 if(uri.contains("?")){ uri = uri.split("[?]")[0]; } ShellUtil.yunDownload(uri.replace(queryPath, ""), kkzipPath); ShellUtil.unZip(kkzipPath,kknumPath); FileUtil.del(kkzipPath); }else { // InputStream in = minIoUploadService.getObject(uri); // FileOutputStream out = new FileOutputStream(sszipPath); // byte[] buffer = new byte[1024]; // int bytesRead; // while ((bytesRead = in.read(buffer)) != -1) { // out.write(buffer, 0, bytesRead); // } // out.flush(); // out.close(); // in.close(); ShellUtil.yunDownloadSs(uri.replace(queryPath, ""), sszipPath); ShellUtil.unZip(sszipPath,ssNumPath); FileUtil.del(sszipPath); } }catch (Exception e){ log.info("下载场景离线包失败:{}",uri,e); } } public void downModel(Integer caseId, String modelGlbUrl) { String path = String.format(FilePath.OFFLINE_OSS_PATH,caseId); JSONArray jsonArray = JSONArray.parseArray(modelGlbUrl); for (Object object : jsonArray) { String res = (String) object; log.info("下载模型:{}",res); res = res.replace(queryPath, ""); if(res.contains(".json") || res.contains(".shp")){ res = new File(res).getParentFile().getPath(); } ShellUtil.yunDownload(res, path +queryPath + res); } } public void downResources(Integer caseId,String urls) { JSONArray jsonArray = JSONArray.parseArray(urls); for (Object object : jsonArray) { String res = (String) object; downResource(caseId,res); } } public void downResources(Integer caseId,JSONArray urls) { for (Object object : urls) { String res = (String) object; downResource(caseId,res); } } public void downResource(Integer caseId,String url) { if(StringUtils.isBlank(url) ){ return; } url = url.replace(queryPath, ""); if( !uploadToOssUtil.existKey(url)){ log.info("downResource文件不存在:{},{}",caseId,url); return; } String path = String.format(FilePath.OFFLINE_OSS_PATH,caseId); ShellUtil.yunDownload(url,path+queryPath+url); } public void downWordByTemplate(Integer caseId,XWPFTemplate template,String name){ // 指定输出文件的路径 String outputPath = String.format(FilePath.OFFLINE_RESOURCE_PACKAGE_PATH,caseId) + name; try { FileOutputStream out = new FileOutputStream(outputPath); template.write(out); out.close(); log.info("文档已成功写入到: " + outputPath); } catch (Exception e) { log.info("写出文档失败:{},{}",caseId,name,e); } } }