ModelServiceImpl.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. package com.fdkankan.fusion.service.impl;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.util.*;
  5. import java.util.concurrent.CompletableFuture;
  6. import java.util.concurrent.ExecutorService;
  7. import java.util.concurrent.ThreadPoolExecutor;
  8. import java.util.stream.Collectors;
  9. import cn.hutool.core.io.FileUtil;
  10. import cn.hutool.core.thread.ThreadUtil;
  11. import com.alibaba.fastjson.JSONArray;
  12. import com.alibaba.fastjson.JSONObject;
  13. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  14. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  15. import com.fdkankan.fusion.common.PageInfo;
  16. import com.fdkankan.fusion.common.util.*;
  17. import com.fdkankan.fusion.common.FilePath;
  18. import com.fdkankan.fusion.common.ResultCode;
  19. import com.fdkankan.fusion.entity.*;
  20. import com.fdkankan.fusion.exception.BusinessException;
  21. import com.fdkankan.fusion.mapper.IModelMapper;
  22. import com.fdkankan.fusion.request.ModelPram;
  23. import com.fdkankan.fusion.response.SceneVo;
  24. import com.fdkankan.fusion.service.ICaseNumService;
  25. import com.fdkankan.fusion.service.ICaseService;
  26. import com.fdkankan.fusion.service.IFusionNumService;
  27. import com.fdkankan.fusion.service.IModelService;
  28. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  29. import com.fdkankan.redis.util.RedisUtil;
  30. import lombok.SneakyThrows;
  31. import lombok.extern.slf4j.Slf4j;
  32. import org.apache.commons.lang3.StringUtils;
  33. import org.springframework.beans.BeanUtils;
  34. import org.springframework.beans.factory.annotation.Autowired;
  35. import org.springframework.beans.factory.annotation.Value;
  36. import org.springframework.scheduling.annotation.Async;
  37. import org.springframework.stereotype.Service;
  38. import org.springframework.web.multipart.MultipartFile;
  39. /**
  40. * <p>
  41. * 服务实现类
  42. * </p>
  43. *
  44. * @author
  45. * @since 2022-08-03
  46. */
  47. @Service
  48. @Slf4j
  49. public class ModelServiceImpl extends ServiceImpl<IModelMapper, Model> implements IModelService {
  50. @Autowired
  51. UploadToOssUtil uploadToOssUtil;
  52. @Autowired
  53. UploadService uploadService;
  54. @Autowired
  55. ICaseNumService caseNumService;
  56. @Autowired
  57. ICaseService caseService;
  58. @Autowired
  59. IFusionNumService fusionNumService;
  60. @Autowired
  61. RedisUtil redisUtil;
  62. @Value("${upload.query-path}")
  63. private String queryPath;
  64. @Value("${spring.profiles.active}")
  65. private String environment;
  66. @Override
  67. public Model uploadObj(MultipartFile file, String username) throws Exception {
  68. if(file.isEmpty()){
  69. throw new BusinessException(ResultCode.UPLOAD_FILE_NO_EXIST);
  70. }
  71. if(file.getSize()>10 * 1024 * 1024 * 100){
  72. throw new BusinessException(ResultCode.UPLOAD_FILE_TO_LONG);
  73. }
  74. //获取文件名
  75. String fileName = file.getOriginalFilename();
  76. if(StringUtils.isEmpty(fileName)){
  77. throw new BusinessException(ResultCode.UPLOAD_FILE_NO_EXIST);
  78. }
  79. if(com.fdkankan.fusion.common.util.StringUtils.isChinese(fileName)){
  80. throw new BusinessException(ResultCode.UPLOAD_FILE_CHINA_NAME);
  81. }
  82. if(fileName.length() >50){
  83. throw new BusinessException(ResultCode.UPLOAD_FILE_NAME_TO_LONG);
  84. }
  85. if(!fileName.toLowerCase().endsWith(".zip")){
  86. throw new BusinessException(ResultCode.UPLOAD_FILE_TYPE_ERROR);
  87. }
  88. //获取文件后缀名
  89. String modelName = fileName.substring(0,fileName.lastIndexOf("."));
  90. Model model = new Model();
  91. model.setModelTitle(modelName);
  92. model.setModelSize(FileWriterUtil.setFileSize(file.getSize()));
  93. model.setUserName(username);
  94. this.save(model);
  95. redisUtil.set(RedisKeyUtil.modelUpload+model.getModelId(),"0");
  96. runThread(file,model,this);
  97. return model;
  98. }
  99. private void setCreateStatus(Model model,Integer status){
  100. String redisKey = RedisKeyUtil.modelCancelUpload+model.getModelId();
  101. if(redisUtil.hasKey(redisKey)){
  102. if(redisUtil.get(redisKey).equals("-2")){
  103. return;
  104. }
  105. }
  106. model.setCreateStatus(status);
  107. this.saveOrUpdate(model);
  108. if(status != 1){
  109. redisUtil.set(RedisKeyUtil.modelUpload+model.getModelId(),status.toString());
  110. }
  111. }
  112. public void runThread(MultipartFile file,Model model,IModelService modelService){
  113. ExecutorService executor = ThreadUtil.newSingleExecutor();
  114. try {
  115. CompletableFuture.runAsync(() -> {
  116. File newObjFile = null;
  117. File objPathFile = null;
  118. File mntFile = null;
  119. File b3dmFile = null;
  120. File osgbFile = null;
  121. try {
  122. String fileName = UUID.randomUUID().toString().replace("-","") +".zip";
  123. String objPath = String.format(FilePath.OBJ_LOCAL_PATH,environment , "modelId_"+model.getModelId()) ;
  124. log.info("uploadObj--ThreadStart-fileName:{},modeId:{}",fileName,model.getModelId());
  125. newObjFile = new File(objPath +"/" + fileName);
  126. if(!newObjFile.getParentFile().exists()){
  127. newObjFile.getParentFile().mkdirs();
  128. }
  129. file.transferTo(newObjFile);
  130. if(fileName.toLowerCase().endsWith(".zip")){
  131. ShellUtil.unZip(newObjFile.getPath(),objPath);
  132. }
  133. objPathFile = new File(objPath );
  134. if(!objPathFile.isDirectory()){
  135. throw new BusinessException(-1,"解压错误");
  136. }
  137. List<File> fileList = new ArrayList<>();
  138. FileWriterUtil.getCanRunList(fileList,objPathFile);
  139. if(fileList.size() <=0){
  140. throw new BusinessException(-1,"可上传文件不存在");
  141. }
  142. File file1 = fileList.get(0);
  143. if(file1 == null){
  144. throw new BusinessException(-1,"可上传文件不存在");
  145. }
  146. if(com.fdkankan.fusion.common.util.StringUtils.isChinese(file1.getName())){
  147. throw new BusinessException(-1,"压缩包中文");
  148. }
  149. String b3dmJsonPath = null;
  150. if(file1.getName().endsWith(".b3dm") ){
  151. b3dmJsonPath = FileWriterUtil.checkB3dmTileset(objPathFile);
  152. if(b3dmJsonPath == null){
  153. throw new BusinessException(-1,"缺少tileset.json文件");
  154. }
  155. }
  156. redisUtil.set(RedisKeyUtil.modelUpload+model.getModelId(),"20");
  157. String glbOssPath = String.format(FilePath.GLB_OSS_PATH,environment, model.getModelId());
  158. String name = file1.getName();
  159. if(name.contains("obj") || name.contains("OBJ")){
  160. glbOssPath = glbOssPath.replace("mesh.glb",file1.getName().replace(".obj",".glb"));
  161. model.setModelDateType("obj");
  162. model.setModelType("glb");
  163. OBJToGLBUtil.objToGlb2(file1.getPath(), file1.getPath().replace(".obj",".glb"));
  164. redisUtil.set(RedisKeyUtil.modelUpload+model.getModelId(),"65");
  165. uploadToOssUtil.uploadOss(file1.getPath().replace(".obj",".glb"),glbOssPath);
  166. if(!uploadToOssUtil.existKey(glbOssPath)){
  167. throw new BusinessException(-1,"缺少.glb文件");
  168. }
  169. }
  170. if(name.contains(".ply")){
  171. model.setModelDateType("ply");
  172. model.setModelType("ply");
  173. }
  174. if(name.contains(".las")){
  175. model.setModelDateType("las");
  176. model.setModelType("las");
  177. }
  178. if("las".equals(model.getModelType()) || "ply".equals(model.getModelType()) ){
  179. mntFile = OBJToGLBUtil.lasOrPlyToBin(file1);
  180. glbOssPath = mntFile.getPath().replace("/mnt/","")+"/webcloud";
  181. redisUtil.set(RedisKeyUtil.modelUpload+model.getModelId(),"65");
  182. uploadToOssUtil.uploadFileOss(mntFile );
  183. if(!uploadToOssUtil.existKey(glbOssPath+"/cloud.js")){
  184. throw new BusinessException(-1,"缺少cloud.js文件");
  185. }
  186. }
  187. model.setModelGlbUrl(JSONArray.toJSONString(Arrays.asList(queryPath + glbOssPath)));
  188. String b3dmPath = objPathFile.getPath().replace(FilePath.LOCAL_BASE_PATH,"fusion/");
  189. if(name.contains(".osgb")){
  190. model.setModelDateType("b3dm");
  191. model.setModelType("b3dm");
  192. redisUtil.set(RedisKeyUtil.modelUpload+model.getModelId(),"60");
  193. String localPath = OBJToGLBUtil.OsgbToB3dm(objPathFile);
  194. osgbFile = new File(localPath.replace("mnt/fusion/b3dm","/mnt/fusion/osgb"));
  195. b3dmFile = new File(localPath);
  196. b3dmJsonPath = FileWriterUtil.checkB3dmTileset(b3dmFile);
  197. if(b3dmJsonPath == null){
  198. throw new BusinessException(-1,"缺少tileset.json文件");
  199. }
  200. redisUtil.set(RedisKeyUtil.modelUpload+model.getModelId(),"80");
  201. String replace = b3dmJsonPath.replace(FilePath.MNT_BASE_PATH, "fusion/test");
  202. File file2 = new File(replace);
  203. ShellUtil.yunUpload(localPath,file2.getParent());
  204. model.setModelGlbUrl((JSONArray.toJSONString(Arrays.asList(queryPath + replace))));
  205. }
  206. if(name.contains(".b3dm") && b3dmJsonPath != null){
  207. model.setModelDateType("b3dm");
  208. model.setModelType("b3dm");
  209. redisUtil.set(RedisKeyUtil.modelUpload+model.getModelId(),"60");
  210. ShellUtil.yunUpload(objPathFile.getPath(),b3dmPath);
  211. model.setModelGlbUrl((JSONArray.toJSONString(Arrays.asList(queryPath + b3dmJsonPath.replace(FilePath.LOCAL_BASE_PATH,"fusion/")))));
  212. }
  213. setCreateStatus(model,1);
  214. modelService.saveOrUpdate(model);
  215. redisUtil.set(RedisKeyUtil.modelUpload+model.getModelId(),"100");
  216. }catch (Exception e){
  217. setCreateStatus(model,-1);
  218. log.error("uploadObj--ThreadError-modeId:{},error:{}",model.getModelId(),e);
  219. }finally {
  220. if(newObjFile!=null){
  221. FileUtil.del(newObjFile);
  222. }
  223. if(objPathFile!=null){
  224. FileUtil.del(objPathFile);
  225. }
  226. if(mntFile!=null){
  227. FileUtil.del(mntFile.getParentFile());
  228. }
  229. if(b3dmFile != null){
  230. FileUtil.del(b3dmFile.getParentFile());
  231. }
  232. if(osgbFile != null){
  233. FileUtil.del(osgbFile.getParentFile());
  234. }
  235. }
  236. }, executor).whenComplete((reslut, e) -> {
  237. log.info("uploadObj--ThreadEnd-modeId:{}",model.getModelId());
  238. });
  239. }catch (Exception e){
  240. setCreateStatus(model,-1);
  241. log.error("uploadObj--ThreadError-modeId:{},error:{}",model.getModelId(),e);
  242. }
  243. }
  244. @Override
  245. public PageInfo pageList(ModelPram param, String token) {
  246. String username = JwtUtil.getUsername(token);
  247. LambdaQueryWrapper<Model> wrapper = new LambdaQueryWrapper<>();
  248. wrapper.eq(Model::getUserName,username);
  249. wrapper.eq(Model::getType,3);
  250. wrapper.notIn(Model::getCreateStatus,-2);
  251. if(param.getStatus()!=null){ //参数2为成功,数据库中成功为1
  252. wrapper.eq(Model::getCreateStatus,param.getStatus() == 2 ? 1 :param.getStatus());
  253. }
  254. if(StringUtils.isNotBlank(param.getModelTitle())){
  255. wrapper.like(Model::getModelTitle,param.getModelTitle());
  256. }
  257. wrapper.orderByDesc(Model::getCreateTime);
  258. Page<Model> page = this.page(new Page<>(param.getPageNum(),param.getPageSize()),wrapper);
  259. for (Model model : page.getRecords()) {
  260. if(model.getType() == 3 && StringUtils.isEmpty(model.getNum())) {
  261. model.setNum(model.getModelId().toString());
  262. }
  263. }
  264. return PageInfo.PageInfo(page);
  265. }
  266. @Override
  267. public void delete(Integer modelId) {
  268. List<CaseNumEntity> caseNumEntityList = caseNumService.getByNum(modelId.toString());
  269. List<FusionNum> fusionNumList = fusionNumService.getByNum(modelId.toString());
  270. if(caseNumEntityList.size() >0 || fusionNumList.size() >0){
  271. StringBuilder title = new StringBuilder();
  272. List<Integer> caseIdIds = caseNumEntityList.parallelStream().map(CaseNumEntity::getCaseId).collect(Collectors.toList());
  273. if(caseIdIds.size() >0){
  274. List<CaseEntity> list = caseService.getByIds(caseIdIds);
  275. List<String> collect = list.parallelStream().map(CaseEntity::getCaseTitle).collect(Collectors.toList());
  276. for (String str : collect) {
  277. title.append(str).append(",");
  278. }
  279. if(title.length()>0){
  280. title.delete(title.length()-1,title.length());
  281. }
  282. }
  283. throw new BusinessException(ResultCode.CASE_USE.code, String.format(ResultCode.CASE_USE.msg,title));
  284. }
  285. Model model = this.getById(modelId);
  286. if(model == null ){
  287. throw new BusinessException(ResultCode.MODEL_NOT_EXIST);
  288. }
  289. this.removeById(modelId);
  290. fusionNumService.deleteByModelId(modelId);
  291. if(StringUtils.isNotBlank(model.getModelGlbUrl())){
  292. uploadService.deleteOssUrl(model.getModelGlbUrl());
  293. }
  294. }
  295. @Override
  296. public List<Model> getListByNum(List<String> numList) {
  297. LambdaQueryWrapper<Model> wrapper = new LambdaQueryWrapper<>();
  298. wrapper.in(Model::getNum,numList);
  299. return this.list(wrapper);
  300. }
  301. @Override
  302. public List<Model> getListByModelIds(List<Integer> modelIds) {
  303. LambdaQueryWrapper<Model> wrapper = new LambdaQueryWrapper<>();
  304. wrapper.in(Model::getModelId,modelIds);
  305. return this.list(wrapper);
  306. }
  307. @Override
  308. public List<Model> getListByModelIdStrs(List<String> numList) {
  309. LambdaQueryWrapper<Model> wrapper = new LambdaQueryWrapper<>();
  310. wrapper.in(Model::getModelId,numList);
  311. wrapper.orderByDesc(Model::getCreateTime);
  312. return this.list(wrapper);
  313. }
  314. @Override
  315. public void deleteByNum(List<String> numList) {
  316. LambdaQueryWrapper<Model> wrapper = new LambdaQueryWrapper<>();
  317. wrapper.in(Model::getNum,numList);
  318. this.remove(wrapper);
  319. }
  320. @Override
  321. public List<Model> getByUserName(String username) {
  322. LambdaQueryWrapper<Model> wrapper = new LambdaQueryWrapper<>();
  323. wrapper.eq(Model::getUserName,username)
  324. .eq(Model::getType,3);
  325. return this.list(wrapper);
  326. }
  327. @Override
  328. public Model getIsNullNewByNum(String num,Integer type) {
  329. LambdaQueryWrapper<Model> wrapper = new LambdaQueryWrapper<>();
  330. wrapper.eq(Model::getNum,num);
  331. wrapper.eq(Model::getType,type);
  332. Model model = this.getOne(wrapper);
  333. if(model == null){
  334. model = new Model();
  335. }
  336. return model;
  337. }
  338. @Override
  339. public Object getInfo(Integer modelId) {
  340. Model model = this.getById(modelId);
  341. if(model == null){
  342. throw new BusinessException(ResultCode.SCENE_NOT_EXIST);
  343. }
  344. SceneVo sceneVo = new SceneVo();
  345. BeanUtils.copyProperties(model,sceneVo);
  346. return sceneVo;
  347. }
  348. @Override
  349. public String uploadObjProgress(Integer modelId) {
  350. String redisKey = RedisKeyUtil.modelUpload+modelId;
  351. String cancel = RedisKeyUtil.modelCancelUpload+modelId;
  352. if(redisUtil.hasKey(cancel)){
  353. return redisUtil.get(cancel);
  354. }
  355. if(redisUtil.hasKey(redisKey)){
  356. return redisUtil.get(redisKey);
  357. }
  358. return "0";
  359. }
  360. @Override
  361. public void cancelUpload(Integer modelId) {
  362. String redisKey = RedisKeyUtil.modelCancelUpload+modelId;
  363. if(redisUtil.hasKey(redisKey)){
  364. return;
  365. }
  366. Model model = this.getById(modelId);
  367. if(model == null){
  368. return;
  369. }
  370. model.setCreateStatus(-2);
  371. this.updateById(model);
  372. redisUtil.set(redisKey,"-2");
  373. }
  374. @Override
  375. public HashMap<String, Model> getMapByNum(List<String> numList) {
  376. HashMap<String,Model> map = new HashMap<>();
  377. List<Model> modelList = this.getListByNum(numList);
  378. modelList.forEach(entity-> map.put(entity.getNum() + entity.getType(),entity));
  379. return map;
  380. }
  381. }