package com.fdkankan.scene.service.impl; import cn.hutool.core.img.ImgUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.lang.UUID; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fdkankan.common.constant.CommonOperStatus; import com.fdkankan.common.constant.ErrorCode; import com.fdkankan.common.constant.SceneConstant; import com.fdkankan.common.constant.SceneVersionType; import com.fdkankan.common.exception.BusinessException; import com.fdkankan.common.util.DateExtUtil; import com.fdkankan.common.util.FileUtils; import com.fdkankan.common.util.SnowflakeIdGenerator; import com.fdkankan.model.constants.ConstantFilePath; import com.fdkankan.model.constants.UploadFilePath; import com.fdkankan.redis.constant.RedisKey; import com.fdkankan.redis.util.RedisUtil; import com.fdkankan.scene.bean.BodySegmentStatusBean; import com.fdkankan.scene.config.FdkkLaserConfig; import com.fdkankan.scene.entity.*; import com.fdkankan.scene.mapper.ISceneMapper; import com.fdkankan.scene.oss.OssUtil; import com.fdkankan.scene.service.*; import com.fdkankan.scene.util.OssBodySegmentUtil; import com.fdkankan.scene.vo.SceneParamVO; import com.fdkankan.web.response.ResultData; 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.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.math.BigDecimal; import java.nio.file.FileSystemException; import java.util.*; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; @Slf4j @Service("sceneService") public class SceneServiceImpl extends ServiceImpl implements ISceneService {//extends ServiceImpl implements ISceneResourceService private static String cloudPointFyunPath = "testdata/%s/data/bundle_%s/building/"; @Value("${queue.bodySegment:body-segment}") private String queueName; @Value("${oss.bodySegment.bucket:4dkankan-huadong}") private String bodySegmentBucket; @Value("${oss.bodySegment.point:oss-cn-shanghai.aliyuncs.com}") private String bodySegmentHost; @Autowired private OssBodySegmentUtil ossBodySegmentUtil; @Autowired private RedisUtil redisUtil; @Autowired private OssUtil ossUtil; @Autowired private IScenePlusService scenePlusService; @Autowired private IScenePlusExtService scenePlusExtService; @Autowired private ISceneEditInfoService sceneEditInfoService; @Autowired private ISceneEditInfoExtService sceneEditInfoExtService; @Autowired private ISceneEditControlsService sceneEditControlsService; @Autowired private ISurveillanceService surveillanceService; @Autowired private ISceneService sceneService; @Override public ResultData uploadBodySegment(MultipartFile file, Integer rotate) throws Exception { if(!FileUtils.checkFileSizeIsLimit(file.getSize(), 10, "M")){ throw new BusinessException(ErrorCode.FAILURE_CODE_4003, "10M"); } String uuid = UUID.randomUUID().toString(); String fileName = file.getOriginalFilename(); String extName = fileName.substring(fileName.lastIndexOf(".")); File tempFile = File.createTempFile(uuid, extName); file.transferTo(tempFile); //判断是否需要旋转 if(Objects.nonNull(rotate) && rotate != 0){ Image rotateImg = ImgUtil.rotate(ImageIO.read(tempFile), rotate); File tempRotateFile = File.createTempFile(uuid + "-rotate", extName); ImgUtil.write(rotateImg, tempRotateFile); tempFile = tempRotateFile; } //校验像素 BufferedImage bufferedImage = ImgUtil.read(tempFile.getPath()); Float scale = 1F; Float widthScale = 1F; Float heightScale = 1F; int width = bufferedImage.getWidth(); int height = bufferedImage.getHeight(); if(width > 2000){ widthScale = new BigDecimal(2000).divide(new BigDecimal(width),5, BigDecimal.ROUND_DOWN).floatValue(); } if(height > 2000){ heightScale = new BigDecimal(2000).divide(new BigDecimal(height),5, BigDecimal.ROUND_DOWN).floatValue(); } scale = widthScale > heightScale ? heightScale : widthScale; ImgUtil.scale(new File(tempFile.getPath()), new File(tempFile.getPath()), scale); String orgImgOssPath = "body_segment/original/" + tempFile.getName(); ossBodySegmentUtil.uploadOss(tempFile.getPath(), orgImgOssPath); // fYunFileService.uploadFile(bodySegmentBucket, tempFile.getPath(), orgImgOssPath); BodySegmentStatusBean bodySegmentStatusBean = BodySegmentStatusBean.builder().uuid(uuid).status(CommonOperStatus.WAITING.code()).build(); redisUtil.set(String.format(RedisKey.SCENE_BODY_SEGMENT, uuid), JSON.toJSONString(bodySegmentStatusBean), RedisKey.CAMERA_EXPIRE_7_TIME); Map map = new HashMap<>(); map.put("uuid", uuid); map.put("imgUrl", "https://" + bodySegmentBucket + "." + bodySegmentHost + "/" + orgImgOssPath); // rabbitMqProducer.sendByWorkQueue(queueName, map); return ResultData.ok(uuid); } public static void main(String[] args) throws IOException { Image rotateImg = ImgUtil.rotate(ImageIO.read(new File("C:\\Users\\dsx\\Desktop\\IMG_0231.HEIC.JPG")), 0); } @Override public void bodySegmentHandler(String imgUrl, String uuid) { String progress = redisUtil.hget(RedisKey.SCENE_BODY_SEGMENT, uuid); BodySegmentStatusBean bodySegmentStatusBean = null; try { if(StrUtil.isEmpty(progress)){ bodySegmentStatusBean = JSON.parseObject(progress, BodySegmentStatusBean.class); } if(Objects.isNull(bodySegmentStatusBean)){ bodySegmentStatusBean = new BodySegmentStatusBean(); bodySegmentStatusBean.setUuid(uuid); } String dir = ConstantFilePath.BASE_PATH + "/bodySegment/" + DateExtUtil.format(Calendar.getInstance().getTime(), DateExtUtil.dateStyle6); String fileName = uuid + ".png"; String imgPath = dir + "/" + fileName; ossBodySegmentUtil.extracted(imgUrl, dir, fileName); if(!FileUtil.exist(imgPath)){ throw new Exception("提取图片失败"); } String targetOssImgPath = "body_segment/segment/" + uuid + ".png"; // ossUtil.uploadFile(targetOssImgPath, imgPath, false); bodySegmentStatusBean.setStatus(CommonOperStatus.SUCCESS.code()); // bodySegmentStatusBean.setImageUrl(fYunFileConfig.getHost() + targetOssImgPath); redisUtil.set(String.format(RedisKey.SCENE_BODY_SEGMENT, uuid), JSON.toJSONString(bodySegmentStatusBean), RedisKey.CAMERA_EXPIRE_7_TIME); } catch (Exception e) { bodySegmentStatusBean.setStatus(CommonOperStatus.FAILD.code()); redisUtil.set(String.format(RedisKey.SCENE_BODY_SEGMENT, uuid), JSON.toJSONString(bodySegmentStatusBean), RedisKey.CAMERA_EXPIRE_7_TIME); }finally { try { //免费版qps不能大于2,故休眠一秒 Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } } } @Override public ResultData getBodySegmentStatus(String uuid) { String progress = redisUtil.get(String.format(RedisKey.SCENE_BODY_SEGMENT, uuid)); if(StrUtil.isEmpty(progress)){ throw new BusinessException(ErrorCode.FAILURE_CODE_5038); } BodySegmentStatusBean bodySegmentStatusBean = JSON.parseObject(progress, BodySegmentStatusBean.class); return ResultData.ok(bodySegmentStatusBean); } @Override public void delete(SceneParamVO param) throws FileSystemException { String sceneNum = param.getSceneNum(); if(StringUtils.isEmpty(sceneNum)){ throw new BusinessException(ErrorCode.FAILURE_CODE_3001); } String[] nums = sceneNum.split(","); List numList = Arrays.asList(nums); List plusList = scenePlusService.getListByNums(numList); scenePlusService.deleteByList(plusList, param.getReserve(), param.isReserveSource()); } @Override public void copyScene(String newNum, String sceneNum, String userName, String dataSource, String bucket) throws Exception { if(StrUtil.isEmpty(newNum) || StrUtil.isEmpty(sceneNum)){ throw new BusinessException(ErrorCode.FAILURE_CODE_3001); } ScenePlus scenePlus = scenePlusService.getScenePlusByNum(sceneNum); if(scenePlus== null){ throw new BusinessException(SceneConstant.FAILURE_CODE_5005, SceneConstant.FAILURE_MSG_5005); } String oldNum = scenePlus.getNum(); Long plusId = scenePlus.getId(); ScenePlusExt plusExt = scenePlusExtService.getScenePlusExtByPlusId(plusId); String oldBucket = plusExt.getYunFileBucket(); String oldDataSource = plusExt.getDataSource(); if(plusExt == null){ throw new BusinessException(SceneConstant.FAILURE_CODE_5005, SceneConstant.FAILURE_MSG_5005); } scenePlus.setNum(newNum); scenePlus.setTitle(scenePlus.getTitle() +"(copy)"); scenePlus.setSceneStatus(0); scenePlus.setId(null); scenePlusService.save(scenePlus); ExecutorService executor = ThreadUtil.newSingleExecutor(); // CompletableFuture.runAsync(() -> { String newVideos = plusExt.getVideos(); if(StrUtil.isNotEmpty(newVideos)){ newVideos = plusExt.getVideos().replaceAll("/data/data" + oldNum, "/scene_view_data/" + newNum + "/data").replaceAll(oldNum, newNum); } plusExt.setId(null); plusExt.setPlusId(scenePlus.getId()); plusExt.setDataSource(dataSource); plusExt.setVideos(newVideos); plusExt.setViewCount(0); plusExt.setYunFileBucket(bucket); scenePlusExtService.save(plusExt); SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(plusId); Long sceneEditInfoId = sceneEditInfo.getId(); sceneEditInfo.setId(null); sceneEditInfo.setScenePlusId(scenePlus.getId()); sceneEditInfo.setSceneProId(null); sceneEditInfo.setTitle(scenePlus.getTitle()); sceneEditInfoService.save(sceneEditInfo); SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByEditInfoId(sceneEditInfoId); sceneEditInfoExt.setId(null); sceneEditInfoExt.setEditInfoId(sceneEditInfo.getId()); sceneEditInfoExt.setScenePlusId(scenePlus.getId()); sceneEditInfoExt.setSceneProId(null); sceneEditInfoExtService.save(sceneEditInfoExt); SceneEditControls sceneEditControls = sceneEditControlsService.getBySceneEditId(sceneEditInfoId); sceneEditControls.setId(null); sceneEditControls.setEditInfoId(sceneEditInfo.getId()); sceneEditControlsService.save(sceneEditControls); List list = surveillanceService.list(new LambdaQueryWrapper().eq(Surveillance::getNum, oldNum)); if (!Objects.isNull(list)) { list.stream().forEach(item -> { item.setNum(newNum); item.setId(null); surveillanceService.save(item); }); } try { // 拷贝场景编辑资源 String oldEditPath = String.format(UploadFilePath.EDIT_PATH, oldNum); String newEditPath = String.format(UploadFilePath.EDIT_PATH, newNum); FileUtil.copyContent(new File(FdkkLaserConfig.getProfile(oldBucket) + File.separator + oldEditPath), new File(FdkkLaserConfig.getProfile(bucket) + File.separator + newEditPath), true); // 拷贝场景展示资源 String oldViewPath = String.format(UploadFilePath.VIEW_PATH, oldNum); String newViewPath = String.format(UploadFilePath.VIEW_PATH, newNum); FileUtil.copyContent(new File(FdkkLaserConfig.getProfile(oldBucket) + File.separator + oldViewPath), new File(FdkkLaserConfig.getProfile(bucket) + File.separator + newViewPath), true); //复制计算目录 FileUtil.copyContent(new File(oldDataSource), new File(dataSource), true); scenePlus.setSceneStatus(-2); scenePlusService.updateById(scenePlus); log.info("复制成功。。。。。"); boolean success = sceneService.updateStatus(newNum,2); log.info("修改复制后的状态-*{}。。。。。",success); }catch (Exception e){ log.error("复制场景失败-V4-sceneNum:{},error:{}",oldNum,e); scenePlus.setSceneStatus(-1); scenePlusService.updateById(scenePlus); boolean success = sceneService.updateStatus(newNum,1); log.info("修改复制后的状态-*{}。。。。。",success); throw new BusinessException(ErrorCode.SYSTEM_BUSY.code(),"复制失败!"); } // }, executor).whenComplete((reslut, e) -> { // log.info("copy-success-"); // }); } @Override public Scene getBySceneCode(String sceneCode) { return this.getOne(new LambdaQueryWrapper().eq(Scene::getSceneCode, sceneCode)); } @Override public String getDataSource(String num, Integer sceneSource, String dataSource) { if(StrUtil.isEmpty(dataSource)){ Scene scene = this.getBySceneCode(num); dataSource = scene.getPath(); } if( dataSource.contains("web_laserData")){//D:\4DMega\4DKK_PROGRAM_DATA\dvt600001_202206291618176080\web_laserData\laserData dataSource = dataSource.substring(0, dataSource.indexOf("web_laserData")); }else{ dataSource = dataSource.concat(File.separator); } return dataSource; } @Override public boolean updateStatus(String sceneCode, Integer status) { LambdaUpdateWrapper wrapper = Wrappers.lambdaUpdate(); wrapper.eq(Scene::getSceneCode, sceneCode); wrapper.set(Scene::getStatus, status); return update(wrapper); } }