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;
/**
*
* pro场景表 服务实现类
*
*
* @author dengsixing
* @since 2021-12-23
*/
@Slf4j
@Service
public class SceneProServiceImpl extends ServiceImpl 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()
.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 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 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 hw = new HashMap<>();
hw.put("height",height);
hw.put("width",width);
return ResultData.ok(hw);
}
private void addOrUpdateHotData(String num, List hotDataList) throws Exception{
Map 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 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 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 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 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 allTagsMap = redisUtil.hmget(key);
List tags = Lists.newArrayList();
List 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 icons = redisUtil.sGet(key);
if(icons == null){
icons = Sets.newHashSet();
}
List iconList = this.sortIcons(tags, icons);
result.put("icons", iconList);
return ResultData.ok(result);
}
private List sortIcons(List tags, Set icons){
//统计使用频次
List 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 iconList = iconBeans.stream().sorted(Comparator.comparing(IconBean::getCount).reversed())
.map(item -> {
return item.getIcon();
}).collect(Collectors.toList());
return iconList;
}
/**
*
保证热点数据安全性,当redis宕机导致热点数据丢失时,可以从文件中读取,恢复到redis
*
* @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 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);
}
}
/**
*
保证icons数据安全性,当redis宕机导致icons数据丢失时,可以从文件中读取,恢复到redis
*
* @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);
}
}
/**
*
热点数据保存
*
* @author dengsixing
* @date 2022/3/3
**/
private void writeHotJson(String num) throws Exception{
String dataKey = String.format(RedisKey.SCENE_HOT_DATA, num);
Map tagMap = redisUtil.hmget(dataKey);
List 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 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 addOrUpdateMap){
if(CollUtil.isEmpty(addOrUpdateMap))
return;
//数据验证,新增、修改状态,hotdata不能为空
Set 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 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 deleteSidList, String bucket) throws Exception {
this.syncHotFromFileToRedis(num);
if(CollUtil.isEmpty(deleteSidList)){
return;
}
//从redis中加载热点数据
String key = String.format(RedisKey.SCENE_HOT_DATA, num);
List 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 hotdataList, boolean deleteBgm) throws Exception {
if(CollUtil.isEmpty(hotdataList)){
return;
}
//删除图片音频视频等资源文件
List 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 map = redisUtil.hmget(key);
if (CollUtil.isEmpty(map)) {
throw new BusinessException(ErrorCode.FAILURE_CODE_7005);
}
List> 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 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()
.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()
.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 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 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()
.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 map = new HashMap();
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 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().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 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 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 listCleanOss4TestCamera(Set 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 listColdStorageScene(int cleanOrigMonth) {
Date time = Calendar.getInstance().getTime();
time = DateUtil.beginOfDay(DateUtil.offset(time, DateField.MONTH, -cleanOrigMonth));
return this.baseMapper.selectColdStorageScene(time);
}
}