123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383 |
- package com.fdkankan.scene.service.impl;
- import cn.hutool.core.collection.CollUtil;
- import cn.hutool.core.date.DateField;
- import cn.hutool.core.date.DateUtil;
- import cn.hutool.core.io.FileUtil;
- import cn.hutool.core.util.StrUtil;
- import cn.hutool.core.util.XmlUtil;
- import cn.hutool.core.util.ZipUtil;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import com.fdkankan.common.constant.*;
- import com.fdkankan.common.exception.BusinessException;
- import com.fdkankan.common.util.CmdUtils;
- import com.fdkankan.common.util.FileUtils;
- import com.fdkankan.fyun.face.FYunFileServiceInterface;
- import com.fdkankan.model.constants.ConstantFileName;
- import com.fdkankan.model.constants.ConstantFilePath;
- import com.fdkankan.model.constants.UploadFilePath;
- import com.fdkankan.model.utils.ComputerUtil;
- import com.fdkankan.model.utils.ConvertUtils;
- import com.fdkankan.model.utils.CreateObjUtil;
- import com.fdkankan.redis.constant.RedisKey;
- import com.fdkankan.redis.constant.RedisLockKey;
- import com.fdkankan.redis.util.RedisLockUtil;
- import com.fdkankan.redis.util.RedisUtil;
- import com.fdkankan.scene.bean.IconBean;
- import com.fdkankan.scene.bean.SceneBean;
- import com.fdkankan.scene.bean.TagBean;
- import com.fdkankan.scene.entity.*;
- import com.fdkankan.scene.mapper.ISceneProMapper;
- import com.fdkankan.scene.service.*;
- import com.fdkankan.scene.vo.*;
- import com.fdkankan.web.response.ResultData;
- import com.google.common.collect.Lists;
- import com.google.common.collect.Sets;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.web.multipart.MultipartFile;
- import org.w3c.dom.Document;
- import org.w3c.dom.Element;
- import javax.annotation.Resource;
- import java.io.File;
- import java.io.IOException;
- import java.nio.charset.StandardCharsets;
- import java.util.*;
- import java.util.Map.Entry;
- import java.util.concurrent.CompletableFuture;
- import java.util.stream.Collectors;
- /**
- * <p>
- * pro场景表 服务实现类
- * </p>
- *
- * @author dengsixing
- * @since 2021-12-23
- */
- @Slf4j
- @Service
- public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro> implements ISceneProService {
- @Value("${fyun.host}")
- private String ossUrlPrefix;
- @Value("${fyun.type}")
- private String fyunType;
- @Value("${main.url}")
- private String mainUrl;
- @Value("${scene.url}")
- private String sceneUrl;
- @Value("${scene.pro.url}")
- private String sceneProUrl;
- @Value("${scene.pro.new.url}")
- private String sceneProNewUrl;
- @Value("${ecs.checkFile.maxTimes:5}")
- private int maxCheckTimes;
- @Value("${ecs.checkFile.waitTime:5000}")
- private int waitTime;
- @Resource
- private FYunFileServiceInterface fYunFileService;
- @Autowired
- private RedisLockUtil redisLockUtil;
- @Autowired
- private RedisUtil redisUtil;
- @Autowired
- private ISceneDataDownloadService sceneDataDownloadService;
- @Autowired
- private ISceneProService sceneProService;
- @Autowired
- private ISceneEditInfoService sceneEditInfoService;
- @Autowired
- private ISceneEditControlsService sceneEditControlsService;
- @Autowired
- private IScenePlusService scenePlusService;
- @Autowired
- private IScenePlusExtService scenePlusExtService;
- @Autowired
- private ISceneUploadService sceneUploadService;
- @Autowired
- private ISceneAsynOperLogService sceneAsynOperLogService;
- @Transactional
- @Override
- public ResultData saveInitialPage(FileNameAndDataParamVO param) throws Exception{
- ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
- if(scenePlus == null){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
- }
- ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
- //更新缩略图url
- String thumbUrl = this.ossUrlPrefix + String.format(UploadFilePath.USER_EDIT_PATH, param.getNum()) + param.getFileName();
- scenePlusExt.setThumb(thumbUrl);
- scenePlusExtService.updateById(scenePlusExt);
- SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
- if(sceneEditInfo == null){
- sceneEditInfo = new SceneEditInfo();
- sceneEditInfo.setScenePlusId(scenePlus.getId());
- sceneEditInfo.setEntry(param.getData());
- sceneEditInfoService.save(sceneEditInfo);
- }else{
- sceneEditInfoService.update(
- new LambdaUpdateWrapper<SceneEditInfo>()
- .set(SceneEditInfo::getEntry, param.getData())
- .setSql("version = version + 1")
- .eq(SceneEditInfo::getId, sceneEditInfo.getId()));
- }
- return ResultData.ok();
- }
- @Override
- public ResultData addOrUpdateTag(SaveTagsParamVO param) throws Exception {
- // ScenePro scenePro = this.findBySceneNum(param.getNum());
- ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
- if (scenePlus == null)
- return ResultData.error(ErrorCode.FAILURE_CODE_5005);
- this.addOrUpdateHotData(param.getNum(), param.getHotDataList());
- this.addOrUpdateIcons(param.getNum(), param.getIcons());
- //写入本地文件,作为备份
- this.writeHotJson(param.getNum());
- //保存数据库
- SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
- sceneEditInfoService.saveTagsToSceneEditInfo(param.getNum(), sceneEditInfo);
- sceneEditInfoService.updateById(sceneEditInfo);
- return ResultData.ok();
- }
- @Override
- public ResultData uploadTagImg(String num, MultipartFile file, String sid, Integer size) throws Exception {
- String extName = FileUtil.extName(file.getOriginalFilename());
- String fragmentPath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "hot_img_fragment/";
- String workPath = fragmentPath + sid;
- String dziPath = workPath + ".dzi";
- String outFilesPath = workPath + "_files/";
- Integer height = null;
- Integer width = null;
- try {
- FileUtil.mkdir(workPath);
- //保存到本地
- String origFilePath = workPath + "/" +file.getOriginalFilename();
- file.transferTo(new File(origFilePath));
- String ossPath = String.format(UploadFilePath.USER_EDIT_PATH, num) + "hotspot/" + sid + "/";
- Map<String, String> uploadMap = new HashMap<>();
- //上传原图
- uploadMap.put(origFilePath, ossPath + sid + "." + extName);
- //切图
- String fragmentCmd = "vips dzsave --tile-size 511 " + origFilePath + " " + workPath;
- CmdUtils.callLine(fragmentCmd);
- if(!ComputerUtil.checkComputeCompleted(dziPath, 5, 200)){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5052);
- }
- List<File> files = FileUtil.loopFiles(outFilesPath);
- files.stream().forEach(v->{
- uploadMap.put(v.getAbsolutePath(), v.getAbsolutePath().replace(outFilesPath, ossPath));
- });
- //是否缩放缩略图,判断:读取dzi中的w h,只要有一个超过320,则进行缩放,如果前端传参,则以传参值为准, 缩放默认值320,否则拿原图作为缩略图,
- String thumbnailName = "thumbnail." + extName;
- Document document = XmlUtil.readXML(new File(dziPath));
- Element rootElement = XmlUtil.getRootElement(document);
- Element sizeElement = XmlUtil.getElement(rootElement, "Size");
- height = Integer.valueOf(sizeElement.getAttribute("Height"));
- width = Integer.valueOf(sizeElement.getAttribute("Width"));
- Integer maxSize = height > width ? height : width;
- if(maxSize > size){
- String thumbnailPath = workPath + "/" + thumbnailName;
- String scaleCmd = "vipsthumbnail " + origFilePath + " -s " + size + " -o " + thumbnailPath;
- CmdUtils.callLine(scaleCmd);
- if(!ComputerUtil.checkComputeCompleted(thumbnailPath, 5, 200)){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5052);
- }
- uploadMap.put(thumbnailPath, ossPath + thumbnailName);
- }else{
- uploadMap.put(origFilePath, ossPath + thumbnailName);
- }
- //上传
- uploadMap.entrySet().stream().forEach(entry->{
- fYunFileService.uploadFile(entry.getKey(), entry.getValue());
- });
- }finally {
- // FileUtil.del(workPath);
- // FileUtil.del(dziPath);
- // FileUtil.del(outFilesPath);
- }
- Map<String, Integer> hw = new HashMap<>();
- hw.put("height",height);
- hw.put("width",width);
- return ResultData.ok(hw);
- }
- private void addOrUpdateHotData(String num, List<HotParamVO> hotDataList) throws Exception{
- Map<String, String> addOrUpdateMap = new HashMap<>();
- int i = 0;
- for (HotParamVO hotParamVO : hotDataList) {
- JSONObject jsonObject = JSON.parseObject(hotParamVO.getHotData());
- jsonObject.put("createTime", Calendar.getInstance().getTimeInMillis() + i++);
- addOrUpdateMap.put(hotParamVO.getSid(), jsonObject.toJSONString());
- }
- this.syncHotFromFileToRedis(num);
- //处理新增和修改数据
- this.addOrUpdateHotDataHandler(num, addOrUpdateMap);
- }
- private void addOrUpdateIcons(String num, List<String> icons) throws Exception{
- if(CollUtil.isEmpty(icons)){
- return;
- }
- this.syncIconsFromFileToRedis(num);
- String key = String.format(RedisKey.SCENE_HOT_ICONS, num);
- redisUtil.sSet(key, icons.toArray());
- }
- @Override
- public ResultData deleteTag(DeleteHotParamVO param) throws Exception {
- // ScenePro scenePro = this.findBySceneNum(param.getNum());
- ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
- if (scenePlus == null)
- throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
- ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
- String bucket = scenePlusExt.getYunFileBucket();
- List<String> deleteSidList = param.getSidList();
- //处理删除状态数据
- this.deleteHotData(param.getNum(), deleteSidList, bucket);
- //删除导览中的热点数据
- this.deleteHotDataFromTourJson(param.getNum(), param.getSidList(), bucket);
- //写入本地文件,作为备份
- this.writeHotJson(param.getNum());
- //保存数据库
- SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
- sceneEditInfoService.saveTagsToSceneEditInfo(param.getNum(), sceneEditInfo);
- sceneEditInfoService.updateById(sceneEditInfo);
- return ResultData.ok();
- }
- private void deleteHotDataFromTourJson(String num, List<String> sidList, String bucket){
- String key = String.format(UploadFilePath.USER_EDIT_PATH, num) + "tour.json";
- String tourJson = fYunFileService.getFileContent(bucket, key);
- if(StrUtil.isEmpty(tourJson)){
- return;
- }
- JSONArray jsonArray = JSON.parseArray(tourJson);
- if(CollUtil.isEmpty(jsonArray)){
- return;
- }
- jsonArray.stream().forEach(tour->{
- JSONObject obj = (JSONObject) tour;
- JSONArray itemArra = obj.getJSONArray("list");
- itemArra.stream().forEach(item->{
- JSONObject itemObj = (JSONObject) item;
- String tagId = itemObj.getString("tagId");
- if(tagId != null && sidList.contains(tagId)){
- itemObj.remove("tagId");
- }
- });
- });
- fYunFileService.uploadFile(bucket, jsonArray.toJSONString().getBytes(StandardCharsets.UTF_8), key);
- }
- @Override
- public ResultData deleteIcons(DeleteHotIconParamVO param) throws Exception {
- ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
- if (scenePlus == null)
- throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
- List<String> fileNameList = param.getFileNameList();
- this.syncIconsFromFileToRedis(param.getNum());
- String key = String.format(RedisKey.SCENE_HOT_ICONS, param.getNum());
- redisUtil.setRemove(key, fileNameList.toArray());
- //写入本地文件,作为备份
- this.writeHotJson(param.getNum());
- //删除oss文件
- sceneUploadService.delete(
- DeleteFileParamVO.builder()
- .num(param.getNum())
- .fileNames(fileNameList)
- .bizType(FileBizType.TAG_ICON.code()).build());
- return ResultData.ok();
- }
- @Override
- public ResultData listTags(String num) throws Exception{
- //保证热点数据安全性,当redis宕机导致热点数据丢失时,可以从文件中读取,恢复到redis
- this.syncHotFromFileToRedis(num);
- //保证icons数据安全性,当redis宕机导致icons数据丢失时,可以从文件中读取,恢复到redis
- this.syncIconsFromFileToRedis(num);
- JSONObject result = new JSONObject();
- //查询缓存是否包含热点数据
- String key = String.format(RedisKey.SCENE_HOT_DATA, num);
- Map<String, String> allTagsMap = redisUtil.hmget(key);
- List<JSONObject> tags = Lists.newArrayList();
- List<TagBean> tagBeanList = new ArrayList<>();
- if(CollUtil.isNotEmpty(allTagsMap)){
- allTagsMap.entrySet().stream().forEach(entry -> {
- JSONObject jsonObject = JSON.parseObject(entry.getValue());
- tagBeanList.add(
- TagBean.builder()
- .createTime(jsonObject.getLong("createTime"))
- .tag(jsonObject).build());
- });
- //按创建时间倒叙排序
- tagBeanList.sort(Comparator.comparingLong(TagBean::getCreateTime).reversed());
- //移除createTime字段
- tags = tagBeanList.stream().map(tagBean -> {
- JSONObject tag = tagBean.getTag();
- tag.remove("createTime");
- return tag;
- }).collect(Collectors.toList());
- }
- result.put("tags", tags);
- //查询缓存是否包含icons
- key = String.format(RedisKey.SCENE_HOT_ICONS, num);
- Set<String> icons = redisUtil.sGet(key);
- if(icons == null){
- icons = Sets.newHashSet();
- }
- List<String> iconList = this.sortIcons(tags, icons);
- result.put("icons", iconList);
- return ResultData.ok(result);
- }
- private List<String> sortIcons(List<JSONObject> tags, Set<String> icons){
- //统计使用频次
- List<IconBean> iconBeans = Lists.newArrayList();
- for (String icon : icons) {
- int count = 0;
- for (JSONObject tag : tags) {
- String sid = tag.getString("icon");
- if(StrUtil.isEmpty(sid) || !icon.equals(sid)){
- continue;
- }
- ++count;
- }
- iconBeans.add(IconBean.builder().icon(icon).count(count).build());
- }
- //排序
- List<String> iconList = iconBeans.stream().sorted(Comparator.comparing(IconBean::getCount).reversed())
- .map(item -> {
- return item.getIcon();
- }).collect(Collectors.toList());
- return iconList;
- }
- /**
- * <p>
- 保证热点数据安全性,当redis宕机导致热点数据丢失时,可以从文件中读取,恢复到redis
- * </p>
- * @author dengsixing
- * @date 2022/3/3
- **/
- private void syncHotFromFileToRedis(String num) throws Exception{
- String key = String.format(RedisKey.SCENE_HOT_DATA, num);
- boolean exist = redisUtil.hasKey(key);
- if(exist){
- return;
- }
- String lockKey = String.format(RedisLockKey.LOCK_HOT_DATA_SYNC, num);
- String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
- boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
- if(!lock){
- throw new BusinessException(ErrorCode.SYSTEM_BUSY);
- }
- try{
- exist = redisUtil.hasKey(key);
- if(exist){
- return;
- }
- String tagsFilePath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "hot.json";
- String tagsData = FileUtils.readUtf8String(tagsFilePath);
- if(StrUtil.isEmpty(tagsData)){
- return;
- }
- JSONObject jsonObject = JSON.parseObject(tagsData);
- JSONArray tagsArr = jsonObject.getJSONArray("tags");
- if(CollUtil.isEmpty(tagsArr)){
- return;
- }
- Map<String, String> map = new HashMap<>();
- for (Object o : tagsArr) {
- JSONObject jo = (JSONObject)o;
- map.put(jo.getString("sid"), jo.toJSONString());
- }
- redisUtil.hmset(key, map);
- }finally {
- redisLockUtil.unlockLua(lockKey, lockVal);
- }
- }
- /**
- * <p>
- 保证icons数据安全性,当redis宕机导致icons数据丢失时,可以从文件中读取,恢复到redis
- * </p>
- * @author dengsixing
- * @date 2022/3/3
- **/
- private void syncIconsFromFileToRedis(String num) throws Exception{
- String key = String.format(RedisKey.SCENE_HOT_ICONS, num);
- boolean exist = redisUtil.hasKey(key);
- if(exist){
- return;
- }
- String lockKey = String.format(RedisLockKey.LOCK_HOT_ICONS_SYNC, num);
- String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
- boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
- if(!lock){
- throw new BusinessException(ErrorCode.SYSTEM_BUSY);
- }
- try{
- exist = redisUtil.hasKey(key);
- if(exist){
- return;
- }
- String tagsFilePath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "hot.json";
- String tagsData = FileUtils.readUtf8String(tagsFilePath);
- if(StrUtil.isEmpty(tagsData)){
- return;
- }
- JSONObject jsonObject = JSON.parseObject(tagsData);
- JSONArray iconArr = jsonObject.getJSONArray("icons");
- if(CollUtil.isEmpty(iconArr)){
- return;
- }
- redisUtil.sSet(key, iconArr.toJavaList(String.class).toArray());
- }finally {
- redisLockUtil.unlockLua(lockKey, lockVal);
- }
- }
- /**
- * <p>
- 热点数据保存
- * </p>
- * @author dengsixing
- * @date 2022/3/3
- **/
- private void writeHotJson(String num) throws Exception{
- String dataKey = String.format(RedisKey.SCENE_HOT_DATA, num);
- Map<String, String> tagMap = redisUtil.hmget(dataKey);
- List<String> tagList = Lists.newArrayList();
- tagMap.entrySet().stream().forEach(entry->{
- if(StrUtil.isNotEmpty(entry.getValue())){
- tagList.add(entry.getValue());
- }
- });
- JSONObject jsonObject = new JSONObject();
- JSONArray tagJsonArr = new JSONArray();
- if(CollUtil.isNotEmpty(tagList)){
- tagList.stream().forEach(hot->{
- tagJsonArr.add(JSONObject.parseObject(hot));
- });
- }
- jsonObject.put("tags", tagJsonArr);
- String iconsKey = String.format(RedisKey.SCENE_HOT_ICONS, num);
- Set<String> iconList = redisUtil.sGet(iconsKey);
- jsonObject.put("icons", iconList);
- String hotJsonPath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "hot.json";
- String lockKey = String.format(RedisLockKey.LOCK_HOT_JSON, num);
- String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
- boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
- if(!lock){
- return;
- }
- try{
- FileUtils.writeFile(hotJsonPath, jsonObject.toJSONString());
- }finally {
- redisLockUtil.unlockLua(lockKey, lockVal);
- }
- }
- private void addOrUpdateHotDataHandler(String num, Map<String, String> addOrUpdateMap){
- if(CollUtil.isEmpty(addOrUpdateMap))
- return;
- //数据验证,新增、修改状态,hotdata不能为空
- Set<String> linkSids = new HashSet<>();
- for (String sid : addOrUpdateMap.keySet()) {
- String hotData = addOrUpdateMap.get(sid);
- if(StrUtil.isEmpty(hotData)){
- throw new BusinessException(ErrorCode.FAILURE_CODE_7004);
- }
- JSONObject jsonObject = JSON.parseObject(hotData);
- String type = jsonObject.getString("type");
- if("link".equals(type)){
- linkSids.add(sid);
- }
- }
- //如果是修改,且由多媒体改成link的方式,将原有的多媒体文件删除
- String key = String.format(RedisKey.SCENE_HOT_DATA, num);
- List<String> updateList = redisUtil.hMultiGet(key, new ArrayList<>(linkSids));
- try {
- this.deleteHotMediaFile(num, updateList, false);
- }catch (Exception e){
- log.error("删除多媒体文件失败", e);
- }
- //批量写入缓存
- redisUtil.hmset(key, addOrUpdateMap);
- }
- private void deleteHotData(String num, List<String> deleteSidList, String bucket) throws Exception {
- this.syncHotFromFileToRedis(num);
- if(CollUtil.isEmpty(deleteSidList)){
- return;
- }
- //从redis中加载热点数据
- String key = String.format(RedisKey.SCENE_HOT_DATA, num);
- List<String> deletDataList = redisUtil.hMultiGet(key, deleteSidList);
- if(CollUtil.isEmpty(deletDataList))
- return;
- //从redis中移除热点数据
- redisUtil.hdel(key, deleteSidList.toArray());
- //删除图片音频视频等资源文件
- this.deleteHotMediaFile(num, deletDataList, true);
- }
- private void deleteHotMediaFile(String num, List<String> hotdataList, boolean deleteBgm) throws Exception {
- if(CollUtil.isEmpty(hotdataList)){
- return;
- }
- //删除图片音频视频等资源文件
- List<String> deleteFileList = new ArrayList<>();
- for (String data : hotdataList) {
- if(StrUtil.isBlank(data)){
- continue;
- }
- JSONObject jsonObject = JSON.parseObject(data);
- //删除背景音乐
- if(deleteBgm){
- JSONObject bgm = jsonObject.getJSONObject("bgm");
- if(Objects.nonNull(bgm) && StrUtil.isNotEmpty(bgm.getString("src"))){
- String bgmSrc = bgm.getString("src");
- deleteFileList.add(bgmSrc);
- }
- }
- String type = jsonObject.getString("type");
- if("media".equals(type)){//V4.13.0版本改成这种方式
- //删除图片、视频
- JSONArray media = jsonObject.getJSONArray("media");
- media.stream().forEach(v->{
- JSONObject o = (JSONObject) v;
- String src = o.getString("src");
- if(StrUtil.isNotEmpty(src)){
- deleteFileList.add(src);
- }
- });
- }
- /* v4.12版本之前是这种方式
- "media": {
- "image": [
- {
- "src": "FfRdi413774.jpg"
- }
- ]
- },
- "type": "image"
- */
- if("image".equals(type) || "audio".equals(type) || "video".equals(type)){
- //删除图片、视频
- JSONObject media = jsonObject.getJSONObject("media");
- JSONArray jsonArray = media.getJSONArray(type);
- jsonArray.stream().forEach(v->{
- JSONObject o = (JSONObject) v;
- String src = o.getString("src");
- if(StrUtil.isNotEmpty(src)){
- deleteFileList.add(src);
- }
- });
- }
- }
- if(CollUtil.isEmpty(deleteFileList)){
- return;
- }
- sceneUploadService.delete(
- DeleteFileParamVO.builder()
- .num(num)
- .fileNames(deleteFileList)
- .bizType("tag-media").build());
- }
- @Override
- public ResultData saveTagsVisible(SaveTagsVisibleParamVO param) throws Exception {
- ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
- if (scenePlus == null ) {
- return ResultData.error(ErrorCode.FAILURE_CODE_5005);
- }
- JSONArray visiblePanos = JSONArray.parseArray(param.getData());
- //如果redis找不到,就从本地文件中reload
- this.syncHotFromFileToRedis(param.getNum());
- //从缓存中获取热点数据,如果为空,抛出异常
- String key = String.format(RedisKey.SCENE_HOT_DATA, param.getNum());
- Map<String, String> map = redisUtil.hmget(key);
- if (CollUtil.isEmpty(map)) {
- throw new BusinessException(ErrorCode.FAILURE_CODE_7005);
- }
- List<Entry<String, String>> allTags = map.entrySet().stream().filter(item -> {
- if (StrUtil.isBlank(item.getValue())) {
- return false;
- }
- return true;
- }).collect(Collectors.toList());
- if (CollUtil.isEmpty(allTags)) {
- throw new BusinessException(ErrorCode.FAILURE_CODE_7005);
- }
- allTags.stream().forEach(entry->{
- JSONObject hot = JSON.parseObject(entry.getValue());
- visiblePanos.stream().forEach(item->{
- if (hot.getString("sid").equals(((JSONObject) item).getString("sid"))) {
- hot.put("visiblePanos", ((JSONObject) item).getJSONArray("value"));
- hot.put("isHidden", ((JSONObject) item).getBoolean("isHidden"));
- entry.setValue(hot.toJSONString());
- }
- });
- });
- //更新版本号
- SceneEditInfo editInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
- sceneEditInfoService.upgradeVersionById(editInfo.getId());
- //放入缓存
- Map<String, String> finalMap = new HashMap<>();
- allTags.stream().forEach(entry->{
- finalMap.put(entry.getKey(), entry.getValue());
- });
- redisUtil.hmset(key, finalMap);
- //写入本地文件,作为备份,以防redis数据丢失
- this.writeHotJson(param.getNum());
- return ResultData.ok();
- }
- @Override
- public ResultData saveRoam(BaseDataParamVO param) throws Exception {
- // ScenePro scenePro = this.findBySceneNum(param.getNum());
- ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
- if (scenePlus == null ) {
- return ResultData.error(ErrorCode.FAILURE_CODE_5005);
- }
- ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
- String bucket = scenePlusExt.getYunFileBucket();
- JSONArray inputData = JSONObject.parseArray(param.getData());
- String localDataPath = String.format(ConstantFilePath.SCENE_DATA_PATH_V4, param.getNum());
- File directory = new File(localDataPath);
- if (!directory.exists()) {
- directory.mkdirs();
- }
- String viewImagesPath = String.format(UploadFilePath.IMG_VIEW_PATH, param.getNum());
- String modeldataUrl = ossUrlPrefix + viewImagesPath + "vision.modeldata?t=" + System.currentTimeMillis();
- //如果是云存储,将vision.modeldata下载到本地,如果是本地存储,场景计算完就已经将这个文件拷贝到编辑目录了存在这个文件了,不需要再下载
- fYunFileService.downloadFile(bucket, viewImagesPath + "vision.modeldata", localDataPath + "vision.modeldata");
- //检查vision.modeldata本地是否存在,不存在抛出异常
- File file = new File(localDataPath + "vision.modeldata");
- if(!file.exists()) {
- return ResultData.error(ErrorCode.FAILURE_CODE_5012);
- }
- //将vision.modeldata解压缩至vision.json
- ConvertUtils.convertVisionModelDataToTxt(localDataPath + "vision.modeldata", localDataPath + "vision.json");
- String str = FileUtils.readFile(localDataPath + "vision.json");
- JSONObject json = JSONObject.parseObject(str);
- JSONArray panos = json.getJSONArray("sweepLocations");
- for (int i = 0; i < panos.size(); ++i) {
- JSONObject pano = panos.getJSONObject(i);
- for (int j = 0; j < inputData.size(); ++j) {
- JSONObject jo = inputData.getJSONObject(j);
- String currentPanoId = jo.getString("panoID");
- JSONArray visibles = jo.getJSONArray("visibles");
- JSONArray visibles3 = jo.getJSONArray("visibles3");
- if (pano.getString("uuid").replaceAll("-", "").equals(currentPanoId)) {
- pano.put("visibles", visibles);
- pano.put("visibles3", visibles3);
- }
- }
- }
- FileUtils.deleteFile(localDataPath + "vision.json");
- FileUtils.deleteFile(localDataPath + "vision.modeldata");
- FileUtils.writeFile(localDataPath + "vision.json", json.toString());
- ConvertUtils.convertTxtToVisionModelData(localDataPath + "vision.json", localDataPath + "vision.modeldata");
- fYunFileService.uploadFile(bucket, localDataPath + "vision.modeldata", viewImagesPath + "vision.modeldata");
- //更新版本号
- SceneEditInfo editInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
- if(Objects.isNull(editInfo)){
- editInfo = new SceneEditInfo();
- editInfo.setScenePlusId(scenePlus.getId());
- sceneEditInfoService.save(editInfo);
- }else{
- sceneEditInfoService.upgradeVersionAndImgVersionById(editInfo.getId());
- //更新scenejson缓存和oss文件版本号
- sceneEditInfoService.upgradeSceneJsonVersion(param.getNum(), editInfo.getVersion() + 1, editInfo.getImgVersion() + 1, bucket);
- }
- return ResultData.ok();
- }
- @Override
- public void updateUserIdByCameraId(Long userId, Long cameraId) {
- this.update(new LambdaUpdateWrapper<ScenePro>()
- .eq(ScenePro::getCameraId, cameraId)
- .set(ScenePro::getUserId, userId));
- }
- @Override
- public ResultData uploadModel(String num, MultipartFile file) throws Exception{
- if(StrUtil.isEmpty(num)){
- throw new BusinessException(ServerCode.PARAM_REQUIRED, "num");
- }
- if(!file.getOriginalFilename().endsWith(".zip")){
- throw new BusinessException(ErrorCode.FAILURE_CODE_7015);
- }
- ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
- if(scenePlus == null){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
- }
- //查询是否存在等待中的异步操作记录,如果存在,抛出业务异常,终止操作
- sceneAsynOperLogService.checkSceneAsynOper(num, null, SceneAsynModuleType.UPLOAD_DOWNLOAD.code() , SceneAsynFuncType.MODEL.code());
- //清除全景图异步操作记录,防止再次下载的时候请求到旧的压缩包
- sceneAsynOperLogService.cleanLog(num, SceneAsynModuleType.UPLOAD_DOWNLOAD.code(), SceneAsynFuncType.MODEL.code());
- ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
- String bucket = scenePlusExt.getYunFileBucket();
- if(ModelKind.THREE_D_TILE.code().equals(scenePlusExt.getModelKind())){
- this.buildModel43dtiles(num, bucket, scenePlusExt.getDataSource(), file);
- }else{
- this.buildModel4Dam(num, bucket, scenePlusExt.getDataSource(), scenePlusExt.getBuildType(), file);
- }
- return ResultData.ok();
- }
- /**
- * 老算法(dam)上传模型逻辑
- * @param num
- * @param bucket
- * @param dataSource
- * @param buildType
- * @throws Exception
- */
- private void buildModel4Dam(String num, String bucket, String dataSource, String buildType, MultipartFile file) throws Exception {
- //文件上传的位置可以自定义
- String path = dataSource + "_obj2txt";
- String zipPath = path + "/zip/";
- String filePath = path + "/extras/";
- String resultPath = path + "/results/";
- //压缩文件处理:解压缩,解压缩后复制等操作
- this.objAndImgFileHandler(resultPath, filePath, zipPath, file);
- //创建data.json
- this.writeDataJson(path);
- CompletableFuture.runAsync(() -> {
- SceneAsynOperLog sceneAsynOperLog = new SceneAsynOperLog();
- sceneAsynOperLog.setNum(num);
- sceneAsynOperLog.setOperType(SceneAsynOperType.UPLOAD.code());
- sceneAsynOperLog.setModule(SceneAsynModuleType.UPLOAD_DOWNLOAD.code());
- sceneAsynOperLog.setFunc(SceneAsynFuncType.MODEL.code());
- sceneAsynOperLogService.save(sceneAsynOperLog);
- try {
- //调用算法,不同的类型调用不同的算法
- if("V2".equals(buildType)){
- CreateObjUtil.objToTxt(path , "1");
- }
- if("V3".equals(buildType)){
- CreateObjUtil.build3dModel(path , "1");
- }
- //算法计算完后,生成压缩文件,上传到oss
- uploadFileofterBuildDamModel(path, filePath, num, bucket);
- //更新版本信息
- ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
- SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
- sceneEditInfoService.update(
- new LambdaUpdateWrapper<SceneEditInfo>()
- .setSql("version = version + 1")
- .setSql("floor_edit_ver = floor_edit_ver + 1")
- .setSql("floor_publish_ver = floor_publish_ver + 1")
- .setSql("img_version = img_version + 1")
- .set(SceneEditInfo::getIsUploadObj, CommonStatus.YES.code())
- .eq(SceneEditInfo::getId, sceneEditInfo.getId()));
- sceneEditInfoService.upgradeSceneJsonVersion(num, sceneEditInfo.getVersion() + 1, sceneEditInfo.getImgVersion() + 1, bucket);
- sceneAsynOperLog.setState(CommonOperStatus.SUCCESS.code());
- } catch (Exception e) {
- log.error("上传dam模型,num:" + num, e);
- sceneAsynOperLog.setState(CommonOperStatus.FAILD.code());
- }
- sceneAsynOperLogService.updateById(sceneAsynOperLog);
- });
- }
- /**
- * 新算法(3dtiles)上传模型逻辑
- * @param num
- * @param bucket
- * @param dataSource
- * @throws Exception
- */
- private void buildModel43dtiles(String num, String bucket, String dataSource, MultipartFile file) throws Exception {
- //文件上传的位置可以自定义
- String path = dataSource + "_obj2Tiles" + File.separator;
- String meshPath = path + "mesh";
- String zipPath = path + "zip" + File.separator;
- String zipFilePath = zipPath + file.getOriginalFilename();
- //压缩文件处理:解压缩,解压缩后复制等操作
- FileUtil.del(path);
- FileUtil.mkdir(zipPath);
- File zipFile = new File(zipFilePath);
- file.transferTo(zipFile);
- ZipUtil.unzip(zipFilePath, meshPath);
- String jsonName = "";
- if(fYunFileService.fileExist(bucket, String.format(UploadFilePath.DATA_VIEW_PATH, num) + "mesh/floors.json")){
- jsonName = "floors.json";
- }
- if(fYunFileService.fileExist(bucket, String.format(UploadFilePath.DATA_VIEW_PATH, num) + "mesh/mesh.json")){
- jsonName = "mesh.json";
- }
- //检测文件
- String floorsJsonPath = meshPath + File.separator + jsonName;
- if(!FileUtil.exist(floorsJsonPath)){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5068.code(), "json file is not exist!");
- }
- String floorsJsonStr = FileUtil.readUtf8String(floorsJsonPath);
- JSONObject floorsJsonObj = JSON.parseObject(floorsJsonStr);
- JSONArray floorArr = floorsJsonObj.getJSONArray("floors");
- if(CollUtil.isEmpty(floorArr)){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5069.code(), "json content is error");
- }
- Set<String> floorNameSet = new HashSet<>();
- String finalJsonName = jsonName;
- floorArr.stream().forEach(item->{
- JSONObject itemObj = (JSONObject) item;
- //楼层目录是否存在
- String name = itemObj.getString("name");
- if(StrUtil.isEmpty(name) || !FileUtil.exist(meshPath + File.separator + name)){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5070);
- }
- //检测obj文件是否存在
- if("floors.json".equals(finalJsonName)){
- String objPath = itemObj.getString("objPath");
- if(StrUtil.isEmpty(objPath) || !FileUtil.exist(path + objPath)){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5070);
- }
- }else{
- JSONArray lods = itemObj.getJSONArray("lods");
- if(CollUtil.isEmpty(lods)){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5069.code(), "json content is error");
- }
- for (Object lod : lods) {
- JSONObject lodObj = (JSONObject) lod;
- String objPath = lodObj.getString("objPath");
- if(StrUtil.isEmpty(objPath) || !FileUtil.exist(path + objPath)){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5070);
- }
- }
- }
- if(floorNameSet.contains(name)){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5069);
- }
- floorNameSet.add(name);
- });
- //读取oss上的floors.jsoon用于校验用户上传的模型楼层数是否一一对应
- String ossFloorsJson = fYunFileService.getFileContent(bucket, String.format(UploadFilePath.DATA_VIEW_PATH, num) + "mesh/" + jsonName);
- JSONObject orginFloorsJsonObj = JSON.parseObject(ossFloorsJson);
- JSONArray orginFloorArr = orginFloorsJsonObj.getJSONArray("floors");
- Set<String> orginFloorNameSet = orginFloorArr.stream().map(item -> {
- JSONObject itemObj = (JSONObject) item;
- return itemObj.getString("name");
- }).collect(Collectors.toSet());
- if(floorNameSet.size() != orginFloorNameSet.size()){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5070);
- }
- orginFloorNameSet.stream().forEach(orginName->{
- if(!floorNameSet.contains(orginName)){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5070);
- }
- });
- SceneAsynOperLog sceneAsynOperLog = new SceneAsynOperLog();
- sceneAsynOperLog.setNum(num);
- sceneAsynOperLog.setOperType(SceneAsynOperType.UPLOAD.code());
- sceneAsynOperLog.setModule(SceneAsynModuleType.UPLOAD_DOWNLOAD.code());
- sceneAsynOperLog.setFunc(SceneAsynFuncType.MODEL.code());
- sceneAsynOperLogService.save(sceneAsynOperLog);
- CompletableFuture.runAsync(() -> {
- try {
- //调用算法
- String command = "bash /home/ubuntu/bin/Obj2Tiles.sh " + path;
- log.info("上传3dtiles模型开始, num:{}, targetPath:{}", num, path);
- CreateObjUtil.callshell(command);
- log.info("上传3dtiles模型结束, num:{}, targetPath:{}", num, path);
- //检测计算结果
- String tilesPath = path + "3dtiles";
- String tilesetJsonPath = tilesPath + File.separator + "tileset.json";
- boolean success = ComputerUtil.checkComputeCompleted(tilesetJsonPath, maxCheckTimes, waitTime);
- if(!success){
- throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
- }
- //删除logs
- FileUtil.del(tilesPath + File.separator + "logs");
- //算法计算完后,生成压缩文件,上传到oss
- //上传3dtiles
- fYunFileService.deleteFolder(bucket, String.format(UploadFilePath.IMG_VIEW_PATH, num) + "3dtiles");
- fYunFileService.uploadFileByCommand(bucket, tilesPath, String.format(UploadFilePath.IMG_VIEW_PATH, num) + "3dtiles");
- //上传mesh
- fYunFileService.deleteFolder(bucket, String.format(UploadFilePath.DATA_VIEW_PATH, num) + "mesh");
- fYunFileService.uploadFileByCommand(bucket, meshPath, String.format(UploadFilePath.DATA_VIEW_PATH, num) + "mesh");
- //更新版本信息
- ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
- SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
- sceneEditInfoService.update(
- new LambdaUpdateWrapper<SceneEditInfo>()
- .setSql("version = version + 1")
- .setSql("floor_edit_ver = floor_edit_ver + 1")
- .setSql("floor_publish_ver = floor_publish_ver + 1")
- .setSql("img_version = img_version + 1")
- .set(SceneEditInfo::getIsUploadObj, CommonStatus.YES.code())
- .eq(SceneEditInfo::getId, sceneEditInfo.getId()));
- sceneEditInfoService.upgradeSceneJsonVersion(num, sceneEditInfo.getVersion() + 1, sceneEditInfo.getImgVersion() + 1, bucket);
- sceneAsynOperLog.setState(CommonOperStatus.SUCCESS.code());
- } catch (Exception e) {
- log.error("上传全景图报错,num:" + num, e);
- sceneAsynOperLog.setState(CommonOperStatus.FAILD.code());
- }
- sceneAsynOperLogService.updateById(sceneAsynOperLog);
- });
- }
- private void uploadFileofterBuildDamModel(String path, String filePath, String sceneNum, String bucket) throws Exception {
- //因为共享目录有延迟,这里循环检测算法是否计算完毕3次,每次隔五秒
- String uploadJsonPath = path + File.separator + "results" +File.separator+"upload.json";
- boolean exist = ComputerUtil.checkComputeCompleted(uploadJsonPath, maxCheckTimes, waitTime);
- if(!exist){
- throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
- }
- String uploadData = FileUtils.readFile(uploadJsonPath);
- JSONObject uploadJson = null;
- JSONArray array = null;
- if(uploadData!=null) {
- uploadJson = JSONObject.parseObject(uploadData);
- array = uploadJson.getJSONArray("upload");
- }
- Map<String,String> map = new HashMap<String,String>();
- JSONObject fileJson = null;
- String fileName = "";
- String imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, sceneNum);
- for(int i = 0, len = array.size(); i < len; i++) {
- fileJson = array.getJSONObject(i);
- fileName = fileJson.getString("file");
- //文件不存在抛出异常
- if (!new File(path + File.separator + "results" + File.separator + fileName).exists()) {
- throw new Exception(path + File.separator + "results" + File.separator + fileName + "文件不存在");
- }
- //tex文件夹
- if (fileJson.getIntValue("clazz") == 15) {
- map.put(path + File.separator + "results" + File.separator + fileName,
- imgViewPath + ConstantFileName.modelUUID + "_50k_texture_jpg_high1/" + fileName.replace("tex/", ""));
- continue;
- }
- }
- String damPath = path + File.separator + "results" +File.separator+ ConstantFileName.modelUUID+"_50k.dam";
- CreateObjUtil.convertTxtToDam( path + File.separator + "results" +File.separator+"modeldata.txt", damPath);
- boolean existDam = ComputerUtil.checkComputeCompleted(damPath, 5, 2);
- if(!existDam){
- throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
- }
- // CreateObjUtil.convertDamToLzma(path + File.separator + "results");
- // CreateObjUtil.convertTxtToDam( path + File.separator + "results" +File.separator+"modeldata.txt", path + File.separator + "results" + File.separator+ConstantFileName.modelUUID+"_50k.dam");
- // map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam.lzma", imgViewPath +ConstantFileName.modelUUID+"_50k.dam.lzma");
- map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam", imgViewPath+ConstantFileName.modelUUID+"_50k.dam");
- String ossMeshPath = String.format(UploadFilePath.DATA_VIEW_PATH, sceneNum) + "mesh";
- //删除oss中的mesh
- fYunFileService.deleteFolder(bucket, ossMeshPath);
- //上传obj相关文件
- List<String> fileNames = FileUtil.listFileNames(filePath);
- fileNames.stream().forEach(name->map.put(filePath + name, ossMeshPath + File.separator + name));
- fYunFileService.uploadMulFiles(bucket, map);
- }
- private void writeDataJson(String path) throws IOException {
- JSONObject dataJson = new JSONObject();
- dataJson.put("obj2txt", true);
- dataJson.put("split_type", "SPLIT_V6");
- dataJson.put("data_describe", "double spherical");
- dataJson.put("skybox_type", "SKYBOX_V5");
- FileUtils.writeFile(path + "/data.json", dataJson.toString());
- }
- private void objAndImgFileHandler(String resultPath, String filePath, String zipPath, MultipartFile file)
- throws Exception {
- FileUtils.delAllFile(resultPath);
- File targetFile = new File(filePath);
- if (!targetFile.exists()) {
- targetFile.mkdirs();
- }else {
- FileUtils.delAllFile(filePath);
- }
- targetFile = new File(zipPath);
- if (!targetFile.exists()) {
- targetFile.mkdirs();
- }else {
- FileUtils.delAllFile(zipPath);
- }
- targetFile = new File(zipPath + file.getOriginalFilename());
- if(!targetFile.getParentFile().exists()){
- targetFile.getParentFile().mkdirs();
- }
- // 保存压缩包到本地
- if(targetFile.exists())
- {
- FileUtils.deleteFile(zipPath + file.getOriginalFilename());
- }
- file.transferTo(targetFile);
- ZipUtil.unzip(zipPath + file.getOriginalFilename(), zipPath + "data/");
- //源文件数据,判断是否有多个文件夹,有多个就提示错误,有一个就将文件夹里数据迁移到extras目录,无直接迁移到extras目录
- boolean flag = false;
- //目录名称,如果不为空,则压缩文件第一层是目录
- String targetName = "";
- File dataFile = new File(zipPath + "data/");
- for(File data : dataFile.listFiles()){
- if(data.isDirectory() && flag){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5018);
- }
- if(data.isDirectory() && !flag){
- flag = true;
- targetName = data.getName();
- }
- }
- //是否包含obj文件
- boolean objFlag = false;
- //是否包含mtl文件
- boolean mtlFlag = false;
- File[] files = null;
- String dataPath = null;
- if(StrUtil.isEmpty(targetName)){
- files = dataFile.listFiles();
- dataPath = zipPath + "data/";
- }else{
- files = new File(zipPath + "data/" + targetName).listFiles();
- dataPath = zipPath + "data/" + targetName + File.separator;
- }
- for(File data : files){
- if(data.isDirectory()){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5018);
- }
- if(data.getName().endsWith(".jpg") || data.getName().endsWith(".png")){
- if(!FileUtils.checkFileSizeIsLimit(data.length(), 1.5, "M")){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5020);
- }
- }
- if(data.getName().endsWith(".obj")){
- if(objFlag){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5019);
- }
- if(!data.getName().equals("mesh.obj")){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5060);
- }
- if(!FileUtils.checkFileSizeIsLimit(data.length(), 20, "M")){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5020);
- }
- objFlag = true;
- FileUtils.copyFile(dataPath + data.getName(), filePath + "mesh.obj", true);
- continue;
- }
- if(data.getName().endsWith(".mtl")){
- mtlFlag = true;
- }
- FileUtils.copyFile(dataPath + data.getName(), filePath + data.getName(), true);
- }
- //压缩文件中必须有且仅有一个obj和mtl文件,否则抛出异常
- if(!mtlFlag || !objFlag){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5059);
- }
- }
- public ResultData downloadModel(String num) throws Exception {
- if(StrUtil.isEmpty(num)){
- throw new BusinessException(ErrorCode.PARAM_REQUIRED);
- }
- ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
- if(scenePlus == null){
- throw new BusinessException(ErrorCode.FAILURE_CODE_5005);
- }
- //查询是否存在等待中的异步操作记录,如果存在,抛出业务异常,终止操作
- sceneAsynOperLogService.checkSceneAsynOper(num,null, SceneAsynModuleType.UPLOAD_DOWNLOAD.code() , SceneAsynFuncType.MODEL.code());
- //清除旧的下载记录
- sceneAsynOperLogService.cleanLog(num, SceneAsynModuleType.UPLOAD_DOWNLOAD.code(), SceneAsynFuncType.MODEL.code(), SceneAsynOperType.DOWNLOAD.code());
- ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
- String bucket = scenePlusExt.getYunFileBucket();
- SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
- //开始异步执行下载全景图压缩包操作
- CompletableFuture.runAsync(() -> {
- SceneAsynOperLog sceneAsynOperLog = new SceneAsynOperLog();
- sceneAsynOperLog.setNum(num);
- sceneAsynOperLog.setOperType(SceneAsynOperType.DOWNLOAD.code());
- sceneAsynOperLog.setModule(SceneAsynModuleType.UPLOAD_DOWNLOAD.code());
- sceneAsynOperLog.setFunc(SceneAsynFuncType.MODEL.code());
- sceneAsynOperLog.setVersion(sceneEditInfo.getImgVersion());
- sceneAsynOperLogService.save(sceneAsynOperLog);
- try {
- String url = null;
- if(ModelKind.THREE_D_TILE.code().equals(scenePlusExt.getModelKind())){
- url = downloadModel43dtiles(num, bucket, scenePlusExt, sceneEditInfo);
- }else{
- url = downloadModel4Dam(num, bucket);
- }
- sceneAsynOperLog.setState(CommonOperStatus.SUCCESS.code());
- sceneAsynOperLog.setUrl(url);
- }catch (Exception e){
- sceneAsynOperLog.setState(CommonOperStatus.FAILD.code());
- log.error("下载模型压缩包失败,num:" + num, e);
- }
- sceneAsynOperLogService.saveOrUpdate(sceneAsynOperLog);
- });
- return ResultData.ok();
- }
- @Override
- public ScenePro getByNum(String num) {
- return this.getOne(new LambdaQueryWrapper<ScenePro>().eq(ScenePro::getNum, num));
- }
- private String downloadModel43dtiles(String num, String bucket, ScenePlusExt scenePlusExt, SceneEditInfo sceneEditInfo){
- //下载mesh到本地
- String meshOssPath = String.format(UploadFilePath.DATA_VIEW_PATH, num) + "mesh/";
- String meshLocalPath = String.format(ConstantFilePath.SCENE_DATA_PATH_V4, num) + "mesh";
- String zipName = num + "_mesh.zip";
- String zipFilePath = String.format(ConstantFilePath.SCENE_DATA_PATH_V4, num) + zipName;
- //下载
- fYunFileService.downloadFileByCommand(bucket, meshLocalPath, meshOssPath);
- //打包
- ZipUtil.zip(meshLocalPath,zipFilePath);
- //上传压缩包
- fYunFileService.uploadFile(bucket, zipFilePath, "downloads/extras/" + zipName);
- //删除本地文件
- FileUtil.del(meshLocalPath);
- FileUtil.del(zipFilePath);
- String url = "downloads/extras/" + zipName;
- return url;
- }
- public static void main(String[] args) throws Exception {
- // ConvertUtils.convertVisionModelDataToTxt( "D:\\test\\vision.modeldata", "D:\\test\\vision.json");
- Document document = XmlUtil.readXML(new File("D:\\Downloads\\aaa.dzi"));
- // XmlUtil.readObjectFromXml()
- // Element image = document.getElementById("Image");
- // getAttribute("size");
- Element rootElement = XmlUtil.getRootElement(document);
- Element size = XmlUtil.getElement(rootElement, "Size");
- String Height = size.getAttribute("Height");
- String Width = size.getAttribute("Width");
- System.out.println(123);
- }
- private String downloadModel4Dam(String num, String bucket){
- String localImagePath = String.format(ConstantFilePath.IMAGESBUFFER_FORMAT, num);
- if(!new File(localImagePath).exists()){
- new File(localImagePath).mkdirs();
- }
- String zipName = num + "_extras.zip";
- String zipPath = localImagePath + zipName;
- String dataViewPath = String.format(UploadFilePath.DATA_VIEW_PATH, num);
- //V3版本去oss下载2048模型
- String meshPath = String.format(ConstantFilePath.DATABUFFER_FORMAT, num) + "mesh";
- FileUtils.deleteDirectory(meshPath);
- fYunFileService.downloadFileByCommand(bucket, meshPath, dataViewPath + "mesh");
- log.info("meshPath="+meshPath);
- if(!new File(meshPath).exists() || new File(meshPath).listFiles().length < 1){
- throw new BusinessException(ErrorCode.FAILURE_CODE_7006);
- }
- for(File file : new File(meshPath).listFiles()){
- if(file.isDirectory()){
- for (File item : file.listFiles()) {
- if(item.getName().endsWith(".obj") && !"output.house.obj".equals(item.getName()) &&
- !"mesh.obj".equals(item.getName())){
- item.delete();
- }
- if(item.getName().endsWith(".mtl") && !"output.house.mtl".equals(item.getName()) &&
- !"mesh.mtl".equals(item.getName())){
- item.delete();
- }
- }
- continue;
- }
- if(file.getName().endsWith(".obj") && !"output.house.obj".equals(file.getName()) &&
- !"mesh.obj".equals(file.getName())){
- file.delete();
- }
- if(file.getName().endsWith(".mtl") && !"output.house.mtl".equals(file.getName()) &&
- !"mesh.mtl".equals(file.getName())){
- file.delete();
- }
- }
- //打包
- ZipUtil.zip(meshPath, zipPath);
- //上传压缩包
- fYunFileService.uploadFile(bucket, zipPath, "downloads/extras/" + zipName);
- String url = "downloads/extras/" + zipName;
- FileUtil.del(zipPath);
- return url;
- }
- @Override
- public List<SceneBean> listCleanOrigScene(int cleanOrigMonth) {
- Date time = Calendar.getInstance().getTime();
- time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -cleanOrigMonth));
- return this.baseMapper.selectCleanOrigScene(time);
- }
- @Override
- public List<SceneBean> listCleanOss4DeletedScene(int month) {
- Date time = Calendar.getInstance().getTime();
- time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -month));
- return this.baseMapper.listCleanOss4DeletedScene(time);
- }
- @Override
- public List<SceneBean> listCleanOss4TestCamera(Set<Long> cameraIds, int month) {
- Date time = Calendar.getInstance().getTime();
- time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -month));
- return this.baseMapper.listCleanOss4TestCamera(cameraIds, time);
- }
- @Override
- public List<SceneBean> listColdStorageScene(int cleanOrigMonth) {
- Date time = Calendar.getInstance().getTime();
- time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -cleanOrigMonth));
- return this.baseMapper.selectColdStorageScene(time);
- }
- }
|