增加3D倾斜模型功能
This commit is contained in:
parent
4f4a110765
commit
b7e2733345
|
|
@ -91,6 +91,8 @@ public interface BusinessConstant {
|
||||||
String FILE_PATH = "file/";
|
String FILE_PATH = "file/";
|
||||||
String IMAGE_PATH = "image/";
|
String IMAGE_PATH = "image/";
|
||||||
String VIDEO_PATH = "video/";
|
String VIDEO_PATH = "video/";
|
||||||
|
String GEO_MODEL_DIR = "/geo/model";
|
||||||
|
String GEO_MODEL_DISK_UPLOAD_PATH = "/geo_model";
|
||||||
String VIDEO_COVER_SUFFIX = "_cover.jpeg";
|
String VIDEO_COVER_SUFFIX = "_cover.jpeg";
|
||||||
String DJI_SIGN = "DJI";
|
String DJI_SIGN = "DJI";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
package com.multictrl.common.utils.kmz;
|
package com.multictrl.common.utils.kmz;
|
||||||
|
|
||||||
|
import com.multictrl.common.exception.RenException;
|
||||||
import com.multictrl.modules.business.dto.RouteDTO;
|
import com.multictrl.modules.business.dto.RouteDTO;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.*;
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -46,4 +49,51 @@ public class KmzUtils {
|
||||||
zos.write(content.getBytes(StandardCharsets.UTF_8));
|
zos.write(content.getBytes(StandardCharsets.UTF_8));
|
||||||
zos.closeEntry();
|
zos.closeEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 zip 输入流解压到目标目录,完整保留 zip 内的目录结构。
|
||||||
|
*
|
||||||
|
* @param zipStream zip 输入流(调用方负责关闭外层流)
|
||||||
|
* @param destDir 目标目录
|
||||||
|
* @throws IOException 解压失败
|
||||||
|
*/
|
||||||
|
public static void unzipToDirectory(InputStream zipStream, Path destDir) throws IOException {
|
||||||
|
// 确保目标目录存在(已存在时不会重复创建)
|
||||||
|
Files.createDirectories(destDir);
|
||||||
|
// 获取规范化的目标目录路径(用于安全校验)
|
||||||
|
Path normalizedDest = destDir.toAbsolutePath().normalize();
|
||||||
|
|
||||||
|
try (ZipInputStream zis = new ZipInputStream(zipStream)) {
|
||||||
|
ZipEntry entry;
|
||||||
|
while ((entry = zis.getNextEntry()) != null) {
|
||||||
|
String entryName = entry.getName();
|
||||||
|
// 拼接并规范化目标文件路径
|
||||||
|
Path targetPath = normalizedDest.resolve(entryName).normalize();
|
||||||
|
|
||||||
|
// 防止 Zip Slip 攻击:确保解压路径仍在目标目录内
|
||||||
|
if (!targetPath.startsWith(normalizedDest)) {
|
||||||
|
throw new IOException("非法路径:" + entryName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
Files.createDirectories(targetPath);
|
||||||
|
} else {
|
||||||
|
// 创建父目录(如果不存在)
|
||||||
|
Path parent = targetPath.getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
Files.createDirectories(parent);
|
||||||
|
}
|
||||||
|
// 使用 NIO 方式将 zip 条目内容写入文件
|
||||||
|
try (OutputStream out = Files.newOutputStream(targetPath)) {
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int len;
|
||||||
|
while ((len = zis.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zis.closeEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
package com.multictrl.modules.business.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.multictrl.common.annotation.ApiOrder;
|
||||||
|
import com.multictrl.common.annotation.LogOperation;
|
||||||
|
import com.multictrl.common.constant.Constant;
|
||||||
|
import com.multictrl.common.exception.ErrorCode;
|
||||||
|
import com.multictrl.common.page.PageData;
|
||||||
|
import com.multictrl.common.utils.Result;
|
||||||
|
import com.multictrl.common.validator.AssertUtils;
|
||||||
|
import com.multictrl.modules.business.dto.GeoPhotoDTO;
|
||||||
|
import com.multictrl.modules.business.service.GeoPhotoService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameters;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地理照片模型
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026-06-05
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("business/geophoto")
|
||||||
|
@Tag(name = "地理模型")
|
||||||
|
@ApiOrder(13)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class GeoPhotoController {
|
||||||
|
private final GeoPhotoService geoPhotoService;
|
||||||
|
|
||||||
|
@GetMapping("page")
|
||||||
|
@Operation(summary = "分页")
|
||||||
|
@Parameters({
|
||||||
|
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始"),
|
||||||
|
@Parameter(name = Constant.LIMIT, description = "每页显示记录数"),
|
||||||
|
@Parameter(name = "type", description = "类型 1正射 2倾斜")
|
||||||
|
})
|
||||||
|
@RequiresPermissions("bus:geophoto:page")
|
||||||
|
public Result<PageData<GeoPhotoDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
||||||
|
PageData<GeoPhotoDTO> page = geoPhotoService.pageList(params);
|
||||||
|
|
||||||
|
return new Result<PageData<GeoPhotoDTO>>().ok(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@Operation(summary = "上传地理资源")
|
||||||
|
@LogOperation("上传地理资源")
|
||||||
|
@RequiresPermissions("bus:geophoto:upload")
|
||||||
|
public Result<Object> upload(@Parameter(description = "模型类型{1:正射,2:倾斜}")
|
||||||
|
@RequestParam("type") String type,
|
||||||
|
@RequestParam("file") MultipartFile file) {
|
||||||
|
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
|
||||||
|
Map<String, String> typeSuffixMap = Map.of("1", "tif", "2", "zip");
|
||||||
|
String expectedSuffix = typeSuffixMap.get(type);
|
||||||
|
if (expectedSuffix == null) {
|
||||||
|
return new Result<>().error(ErrorCode.PARAMS_ERROR, "模型类型");
|
||||||
|
}
|
||||||
|
if (!expectedSuffix.equals(suffix)) {
|
||||||
|
return new Result<>().error(ErrorCode.FILE_FORMAT_ERROR, expectedSuffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
geoPhotoService.upload(type, file);
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
@Operation(summary = "获取地理资源")
|
||||||
|
public Result<List<GeoPhotoDTO>> get(@Parameter(description = "类型{1:正射,2:倾斜}")
|
||||||
|
@RequestParam("type") String type) {
|
||||||
|
List<GeoPhotoDTO> layerInfo = geoPhotoService.getGeoList(type);
|
||||||
|
|
||||||
|
return new Result<List<GeoPhotoDTO>>().ok(layerInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping
|
||||||
|
@Operation(summary = "删除")
|
||||||
|
@LogOperation("删除")
|
||||||
|
@RequiresPermissions("bus:geophoto:delete")
|
||||||
|
public Result<Object> delete(@RequestParam Long id) {
|
||||||
|
geoPhotoService.remove(id);
|
||||||
|
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getDiskModel")
|
||||||
|
@Operation(summary = "获取磁盘模型")
|
||||||
|
@LogOperation("获取磁盘模型")
|
||||||
|
@RequiresPermissions("bus:geophoto:getDiskModel")
|
||||||
|
public Result<List<GeoPhotoDTO>> getDiskModel() {
|
||||||
|
List<GeoPhotoDTO> diskData = geoPhotoService.getDiskMap();
|
||||||
|
|
||||||
|
return new Result<List<GeoPhotoDTO>>().ok(diskData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/uploadModelDisk")
|
||||||
|
@Operation(summary = "磁盘上传模型")
|
||||||
|
@LogOperation("磁盘上传模型")
|
||||||
|
@RequiresPermissions("bus:geophoto:uploadModelDisk")
|
||||||
|
public Result<List<GeoPhotoDTO>> uploadModelDisk(@RequestBody List<String> names) {
|
||||||
|
AssertUtils.isListEmpty(names, "模型名称");
|
||||||
|
geoPhotoService.uploadModelDisk(names);
|
||||||
|
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.multictrl.modules.business.dao;
|
||||||
|
|
||||||
|
import com.multictrl.common.dao.BaseDao;
|
||||||
|
import com.multictrl.modules.business.entity.GeoPhotoEntity;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地理照片模型
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026-06-05
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface GeoPhotoDao extends BaseDao<GeoPhotoEntity> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.multictrl.modules.business.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地理照片模型
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026-06-05
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(name = "地理照片模型")
|
||||||
|
public class GeoPhotoDTO implements Serializable {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "标识")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "名称")
|
||||||
|
private String geoName;
|
||||||
|
|
||||||
|
@Schema(description = "大小")
|
||||||
|
private String geoSize;
|
||||||
|
|
||||||
|
@Schema(description = "类型 1正射 2倾斜")
|
||||||
|
private String geoType;
|
||||||
|
|
||||||
|
@Schema(description = "状态 0进行中 1完成 2失败")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Schema(description = "时间")
|
||||||
|
private Date createDate;
|
||||||
|
|
||||||
|
@Schema(description = "资源地址")
|
||||||
|
private String url;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.multictrl.modules.business.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地理照片模型
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026-06-05
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("bus_geo_photo")
|
||||||
|
public class GeoPhotoEntity {
|
||||||
|
/**
|
||||||
|
* 标识
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 名称
|
||||||
|
*/
|
||||||
|
private String geoName;
|
||||||
|
/**
|
||||||
|
* 大小
|
||||||
|
*/
|
||||||
|
private String geoSize;
|
||||||
|
/**
|
||||||
|
* 类型 1正射 2倾斜
|
||||||
|
*/
|
||||||
|
private String geoType;
|
||||||
|
/**
|
||||||
|
* 状态 0进行中 1完成 2失败
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
/**
|
||||||
|
* 创建人
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private Long creator;
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private Date createDate;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.multictrl.modules.business.service;
|
||||||
|
|
||||||
|
import com.multictrl.common.page.PageData;
|
||||||
|
import com.multictrl.common.service.CrudService;
|
||||||
|
import com.multictrl.modules.business.dto.GeoPhotoDTO;
|
||||||
|
import com.multictrl.modules.business.entity.GeoPhotoEntity;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地理照片模型
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026-06-05
|
||||||
|
*/
|
||||||
|
public interface GeoPhotoService extends CrudService<GeoPhotoEntity, GeoPhotoDTO> {
|
||||||
|
|
||||||
|
//分页列表
|
||||||
|
PageData<GeoPhotoDTO> pageList(Map<String, Object> params);
|
||||||
|
|
||||||
|
//上传地理资源
|
||||||
|
void upload(String type, MultipartFile file);
|
||||||
|
|
||||||
|
//获取地理资源
|
||||||
|
List<GeoPhotoDTO> getGeoList(String type);
|
||||||
|
|
||||||
|
//删除地理资源
|
||||||
|
void remove(Long id);
|
||||||
|
|
||||||
|
//获取磁盘地图
|
||||||
|
List<GeoPhotoDTO> getDiskMap();
|
||||||
|
|
||||||
|
//磁盘上传模型
|
||||||
|
void uploadModelDisk(List<String> names);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,232 @@
|
||||||
|
package com.multictrl.modules.business.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.core.io.file.FileNameUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.multictrl.common.constant.BusinessConstant;
|
||||||
|
import com.multictrl.common.exception.ErrorCode;
|
||||||
|
import com.multictrl.common.exception.RenException;
|
||||||
|
import com.multictrl.common.page.PageData;
|
||||||
|
import com.multictrl.common.service.impl.CrudServiceImpl;
|
||||||
|
import com.multictrl.common.utils.ConvertUtils;
|
||||||
|
import com.multictrl.common.utils.Utils;
|
||||||
|
import com.multictrl.common.utils.kmz.KmzUtils;
|
||||||
|
import com.multictrl.modules.business.dao.GeoPhotoDao;
|
||||||
|
import com.multictrl.modules.business.dto.GeoPhotoDTO;
|
||||||
|
import com.multictrl.modules.business.entity.GeoPhotoEntity;
|
||||||
|
import com.multictrl.modules.business.service.GeoPhotoService;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地理照片模型
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026-06-05
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class GeoPhotoServiceImpl extends CrudServiceImpl<GeoPhotoDao, GeoPhotoEntity, GeoPhotoDTO> implements GeoPhotoService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryWrapper<GeoPhotoEntity> getWrapper(Map<String, Object> params) {
|
||||||
|
String id = (String) params.get("id");
|
||||||
|
String geoType = (String) params.get("type");
|
||||||
|
|
||||||
|
QueryWrapper<GeoPhotoEntity> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq(StrUtil.isNotBlank(id), "id", id);
|
||||||
|
wrapper.eq(StrUtil.isNotBlank(geoType), "geo_type", geoType);
|
||||||
|
wrapper.orderByDesc("create_date");
|
||||||
|
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageData<GeoPhotoDTO> pageList(Map<String, Object> params) {
|
||||||
|
PageData<GeoPhotoDTO> page = page(params);
|
||||||
|
for (GeoPhotoDTO dto : page.getList()) {
|
||||||
|
String geoSize = dto.getGeoSize();
|
||||||
|
if (StrUtil.isNotBlank(geoSize)) {
|
||||||
|
dto.setGeoSize(Utils.formatBytes(Long.parseLong(geoSize)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void upload(String type, MultipartFile file) {
|
||||||
|
GeoPhotoEntity geoPhotoEntity = new GeoPhotoEntity();
|
||||||
|
geoPhotoEntity.setGeoName(FileUtil.mainName(file.getOriginalFilename()));
|
||||||
|
geoPhotoEntity.setGeoSize(file.getSize() + "");
|
||||||
|
geoPhotoEntity.setGeoType(type);
|
||||||
|
geoPhotoEntity.setStatus("0");
|
||||||
|
baseDao.insert(geoPhotoEntity);
|
||||||
|
if ("1".equals(type)) {//正射
|
||||||
|
return;
|
||||||
|
} else {//倾斜
|
||||||
|
uploadMode(geoPhotoEntity, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<GeoPhotoDTO> getGeoList(String type) {
|
||||||
|
QueryWrapper<GeoPhotoEntity> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq("geo_type", type);
|
||||||
|
wrapper.eq("status", "1");
|
||||||
|
wrapper.orderByDesc("create_date");
|
||||||
|
List<GeoPhotoEntity> list = baseDao.selectList(wrapper);
|
||||||
|
if ("1".equals(type)) {//正射
|
||||||
|
return List.of();
|
||||||
|
} else {//倾斜
|
||||||
|
List<GeoPhotoDTO> dtoList = ConvertUtils.sourceToTarget(list, GeoPhotoDTO.class);
|
||||||
|
for (GeoPhotoDTO dto : dtoList) {
|
||||||
|
String geoName = dto.getGeoName();
|
||||||
|
if (StrUtil.isNotBlank(geoName)) {
|
||||||
|
dto.setUrl(BusinessConstant.GEO_MODEL_DIR + "/" + geoName + "/tileset.json");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dtoList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@Override
|
||||||
|
public void remove(Long id) {
|
||||||
|
try {
|
||||||
|
GeoPhotoEntity geoPhotoEntity = selectById(id);
|
||||||
|
if ("1".equals(geoPhotoEntity.getGeoType())) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
//删除数据
|
||||||
|
deleteById(id);
|
||||||
|
//删除文件
|
||||||
|
File file = new File(BusinessConstant.GEO_MODEL_DIR + "/" + geoPhotoEntity.getGeoName());
|
||||||
|
if (file.exists()) {
|
||||||
|
FileUtil.del(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RenException(ErrorCode.DELETE_FAIL, "地理资源");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<GeoPhotoDTO> getDiskMap() {
|
||||||
|
List<GeoPhotoDTO> list = new ArrayList<>();
|
||||||
|
File directory = new File(BusinessConstant.GEO_MODEL_DISK_UPLOAD_PATH);
|
||||||
|
if (directory.exists() && directory.isDirectory()) {
|
||||||
|
for (File file : Objects.requireNonNull(directory.listFiles())) {
|
||||||
|
String name = file.getName();
|
||||||
|
String extName = FileUtil.extName(name);
|
||||||
|
GeoPhotoDTO dto = new GeoPhotoDTO();
|
||||||
|
dto.setGeoName(name);
|
||||||
|
dto.setGeoSize(Utils.formatBytes(file.length()));
|
||||||
|
if ("tif".equals(extName)) {
|
||||||
|
dto.setGeoType("1");
|
||||||
|
list.add(dto);
|
||||||
|
} else if ("zip".equals(extName)) {
|
||||||
|
dto.setGeoType("2");
|
||||||
|
list.add(dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadModelDisk(List<String> names) {
|
||||||
|
for (String name : names) {
|
||||||
|
String sourceFile = BusinessConstant.GEO_MODEL_DISK_UPLOAD_PATH + File.separator + name;
|
||||||
|
String extName = FileUtil.extName(name);
|
||||||
|
if ("tif".equals(extName)) {
|
||||||
|
return;
|
||||||
|
} else if ("zip".equals(extName)) {
|
||||||
|
File file = new File(sourceFile);
|
||||||
|
if (file.exists()) {
|
||||||
|
GeoPhotoEntity entity = new GeoPhotoEntity();
|
||||||
|
entity.setGeoName(FileUtil.mainName(name));
|
||||||
|
entity.setGeoSize(file.length() + "");
|
||||||
|
entity.setGeoType("2");
|
||||||
|
entity.setStatus("0");
|
||||||
|
baseDao.insert(entity);
|
||||||
|
//解压文件
|
||||||
|
CompletableFuture.runAsync(() -> {
|
||||||
|
try (FileInputStream fis = new FileInputStream(file)) {
|
||||||
|
KmzUtils.unzipToDirectory(fis, Paths.get(BusinessConstant.GEO_MODEL_DIR));
|
||||||
|
entity.setStatus("1");
|
||||||
|
} catch (Exception e) {
|
||||||
|
entity.setStatus("2");
|
||||||
|
log.error("模型压缩文件解压失败,文件名称: {}", name, e);
|
||||||
|
} finally {
|
||||||
|
baseDao.updateById(entity);
|
||||||
|
// 删除临时文件
|
||||||
|
if (file.exists()) {
|
||||||
|
boolean delete = file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).exceptionally(throwable -> {
|
||||||
|
log.error("模型压缩文件解压失败,文件名称: {}", name, throwable);
|
||||||
|
entity.setStatus("2");
|
||||||
|
baseDao.updateById(entity);
|
||||||
|
if (file.exists()) {
|
||||||
|
boolean delete = file.delete();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//上传倾斜模型
|
||||||
|
private void uploadMode(GeoPhotoEntity geoPhotoEntity, MultipartFile file) {
|
||||||
|
// 创建临时文件
|
||||||
|
File tempFile;
|
||||||
|
try {
|
||||||
|
tempFile = File.createTempFile("upload_geo_photo_" + System.currentTimeMillis(), ".zip");
|
||||||
|
file.transferTo(tempFile);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("创建临时文件失败", e);
|
||||||
|
geoPhotoEntity.setStatus("2");
|
||||||
|
baseDao.updateById(geoPhotoEntity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//解压文件
|
||||||
|
File finalTempFile = tempFile;
|
||||||
|
CompletableFuture.runAsync(() -> {
|
||||||
|
try (FileInputStream fis = new FileInputStream(finalTempFile)) {
|
||||||
|
KmzUtils.unzipToDirectory(fis, Paths.get(BusinessConstant.GEO_MODEL_DIR));
|
||||||
|
geoPhotoEntity.setStatus("1");
|
||||||
|
} catch (Exception e) {
|
||||||
|
geoPhotoEntity.setStatus("2");
|
||||||
|
log.error("模型压缩文件解压失败,文件名称: {}", file.getOriginalFilename(), e);
|
||||||
|
} finally {
|
||||||
|
baseDao.updateById(geoPhotoEntity);
|
||||||
|
// 删除临时文件
|
||||||
|
if (finalTempFile.exists()) {
|
||||||
|
boolean delete = finalTempFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).exceptionally(throwable -> {
|
||||||
|
log.error("模型压缩文件解压失败,文件名称: {}", file.getOriginalFilename(), throwable);
|
||||||
|
geoPhotoEntity.setStatus("2");
|
||||||
|
baseDao.updateById(geoPhotoEntity);
|
||||||
|
if (finalTempFile.exists()) {
|
||||||
|
boolean delete = finalTempFile.delete();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -78,6 +78,6 @@ influx:
|
||||||
org: dj
|
org: dj
|
||||||
|
|
||||||
host:
|
host:
|
||||||
ip: 192.168.1.193
|
ip: 223.108.157.174
|
||||||
port: 61620
|
port: 61620
|
||||||
is-ssl: false
|
is-ssl: false
|
||||||
|
|
@ -36,8 +36,8 @@ spring:
|
||||||
matching-strategy: ANT_PATH_MATCHER
|
matching-strategy: ANT_PATH_MATCHER
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
max-file-size: 500MB
|
max-file-size: 2GB
|
||||||
max-request-size: 500MB
|
max-request-size: 2GB
|
||||||
enabled: true
|
enabled: true
|
||||||
data:
|
data:
|
||||||
redis:
|
redis:
|
||||||
|
|
|
||||||
|
|
@ -67,4 +67,6 @@ public interface ErrorCode {
|
||||||
int UAV_LIGHT_INDEX_NOT_EXIST = 20026;
|
int UAV_LIGHT_INDEX_NOT_EXIST = 20026;
|
||||||
int DICT_NOT_DELETE = 20027;
|
int DICT_NOT_DELETE = 20027;
|
||||||
int DICT_EXIST = 20028;
|
int DICT_EXIST = 20028;
|
||||||
|
int FILE_FORMAT_ERROR = 20029;
|
||||||
|
int DELETE_FAIL = 20030;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
10030=\u5220\u9664\u6587\u4EF6\u5931\u8D25{0}
|
10030=\u5220\u9664\u6587\u4EF6\u5931\u8D25{0}
|
||||||
#business
|
#business
|
||||||
20001=\u822a\u7ebf\u5df2\u5b58\u5728
|
20001=\u822a\u7ebf\u5df2\u5b58\u5728
|
||||||
20002=\u53C2\u6570\u9519\u8BEF
|
20002={0}\u53C2\u6570\u9519\u8BEF
|
||||||
20003=\u8BF7\u6C42\u8D85\u65F6\uFF0C\u672A\u6536\u5230\u673A\u573A\u56DE\u590D
|
20003=\u8BF7\u6C42\u8D85\u65F6\uFF0C\u672A\u6536\u5230\u673A\u573A\u56DE\u590D
|
||||||
20004=\u673A\u573A\u6267\u884C\u6210\u529F
|
20004=\u673A\u573A\u6267\u884C\u6210\u529F
|
||||||
20005=\u673A\u5E93\u89C6\u9891\u6807\u8BC6\u672A\u83B7\u53D6\uFF0C\u8BF7\u5C1D\u8BD5\u91CD\u542F\u673A\u5E93\u6216\u8005\u8C03\u8BD5\u6A21\u5F0F\u98DE\u673A\u5F00\u5173\u673A
|
20005=\u673A\u5E93\u89C6\u9891\u6807\u8BC6\u672A\u83B7\u53D6\uFF0C\u8BF7\u5C1D\u8BD5\u91CD\u542F\u673A\u5E93\u6216\u8005\u8C03\u8BD5\u6A21\u5F0F\u98DE\u673A\u5F00\u5173\u673A
|
||||||
|
|
@ -55,4 +55,6 @@
|
||||||
20025={0}\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u8DEF\u5F84\u662F\u5426\u6B63\u786E
|
20025={0}\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u8DEF\u5F84\u662F\u5426\u6B63\u786E
|
||||||
20026=\u98DE\u673A\u63A2\u7167\u706F\u8D1F\u8F7D\u4F4D\u7F6E\u672A\u83B7\u53D6\uFF0C\u8BF7\u68C0\u67E5\u98DE\u673A\u662F\u5426\u5F00\u673A
|
20026=\u98DE\u673A\u63A2\u7167\u706F\u8D1F\u8F7D\u4F4D\u7F6E\u672A\u83B7\u53D6\uFF0C\u8BF7\u68C0\u67E5\u98DE\u673A\u662F\u5426\u5F00\u673A
|
||||||
20027={0}\u5B57\u5178\u7981\u6B62\u5220\u9664
|
20027={0}\u5B57\u5178\u7981\u6B62\u5220\u9664
|
||||||
20028={0}\u5B57\u5178\u5DF2\u7ECF\u5B58\u5728
|
20028={0}\u5B57\u5178\u5DF2\u7ECF\u5B58\u5728
|
||||||
|
20029=\u8bf7\u4e0a\u4f20{0}\u683c\u5f0f\u6587\u4ef6
|
||||||
|
20030=\u5220\u9664{0}\u5931\u8D25\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458
|
||||||
|
|
@ -55,6 +55,8 @@ cp ./file/wait/wait-for-it.sh /root/dj_multictrl_data/wait/wait-for-it.sh
|
||||||
|
|
||||||
mkdir -p /root/dj_multictrl_data/mongodb/data
|
mkdir -p /root/dj_multictrl_data/mongodb/data
|
||||||
|
|
||||||
|
mkdir -p /geo_model
|
||||||
|
|
||||||
mkdir -p /root/dj_multictrl_data/script
|
mkdir -p /root/dj_multictrl_data/script
|
||||||
mkdir -p /root/dj_multictrl_data/script/logs
|
mkdir -p /root/dj_multictrl_data/script/logs
|
||||||
cp ./file/script/cleanup_srs_record_videos.sh /root/dj_multictrl_data/script/
|
cp ./file/script/cleanup_srs_record_videos.sh /root/dj_multictrl_data/script/
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ services:
|
||||||
- /data/dj_multictrl_data/minio/data:/data
|
- /data/dj_multictrl_data/minio/data:/data
|
||||||
- /data/dj_multictrl_data/live_record:/data/live_record
|
- /data/dj_multictrl_data/live_record:/data/live_record
|
||||||
- /data/dj_multictrl_data/geoserver:/data/geoserver
|
- /data/dj_multictrl_data/geoserver:/data/geoserver
|
||||||
|
- /data/dj_multictrl_data/geo/model:/data/geo/model
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
|
||||||
dj-multictrl-pgsql:
|
dj-multictrl-pgsql:
|
||||||
|
|
@ -174,8 +175,10 @@ services:
|
||||||
- /data/dj_multictrl_data/live_record:/live_record
|
- /data/dj_multictrl_data/live_record:/live_record
|
||||||
- /root/dj_multictrl_data/ffmpeg/ffmpeg:/usr/bin/ffmpeg
|
- /root/dj_multictrl_data/ffmpeg/ffmpeg:/usr/bin/ffmpeg
|
||||||
- /data/dj_multictrl_data/minio/data:/minio_data
|
- /data/dj_multictrl_data/minio/data:/minio_data
|
||||||
|
- /data/dj_multictrl_data/geo/model:/geo/model
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
- /root/dj_multictrl_data/api/tmp:/tmp
|
- /root/dj_multictrl_data/api/tmp:/tmp
|
||||||
|
- /geo_model:/geo_model
|
||||||
command:
|
command:
|
||||||
- /bin/bash
|
- /bin/bash
|
||||||
- -c
|
- -c
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,12 @@ http {
|
||||||
proxy_pass http://dj-multictrl-api:8080/api/;
|
proxy_pass http://dj-multictrl-api:8080/api/;
|
||||||
}
|
}
|
||||||
|
|
||||||
#location ~* /live_record/(.+)$ {
|
location /geo/model {
|
||||||
# add_header Access-Control-Allow-Origin *;
|
add_header Access-Control-Allow-Origin *;
|
||||||
# add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
|
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
|
||||||
# add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
|
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
|
||||||
# alias /live_record/$1;
|
root /data;
|
||||||
#}
|
}
|
||||||
|
|
||||||
location ~* /video/(.+)$ {
|
location ~* /video/(.+)$ {
|
||||||
add_header Access-Control-Allow-Origin *;
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
|
|
||||||
|
|
@ -2144,6 +2144,39 @@ INSERT INTO "public"."sys_dict_data" ("id", "dict_type_id", "dict_label", "dict_
|
||||||
VALUES (2060253516358848514, 2060253239434121218, 'Ars550', 'Ars550', '', 0, 1067246875800000001,
|
VALUES (2060253516358848514, 2060253239434121218, 'Ars550', 'Ars550', '', 0, 1067246875800000001,
|
||||||
'2026-05-29 14:54:50.617', 1067246875800000001, '2026-05-29 14:54:50.617', 'source-material/Ars550.png');
|
'2026-05-29 14:54:50.617', 1067246875800000001, '2026-05-29 14:54:50.617', 'source-material/Ars550.png');
|
||||||
|
|
||||||
|
--2026/6/5
|
||||||
|
DROP TABLE IF EXISTS "public"."bus_geo_photo";
|
||||||
|
CREATE TABLE "public"."bus_geo_photo"
|
||||||
|
(
|
||||||
|
"id" int8 NOT NULL,
|
||||||
|
"geo_name" varchar(255) COLLATE "pg_catalog"."default",
|
||||||
|
"geo_size" varchar(50) COLLATE "pg_catalog"."default",
|
||||||
|
"geo_type" char(1) COLLATE "pg_catalog"."default",
|
||||||
|
"status" char(1) COLLATE "pg_catalog"."default",
|
||||||
|
"creator" int8,
|
||||||
|
"create_date" timestamp(6)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."bus_geo_photo"."id" IS '标识';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."bus_geo_photo"."geo_name" IS '名称';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."bus_geo_photo"."geo_size" IS '大小';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."bus_geo_photo"."geo_type" IS '类型 1正射 2倾斜';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."bus_geo_photo"."status" IS '状态 0进行中 1完成 2失败';
|
||||||
|
COMMENT
|
||||||
|
ON TABLE "public"."bus_geo_photo" IS '地理照片模型';
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Primary Key structure for table bus_geo_photo
|
||||||
|
-- ----------------------------
|
||||||
|
ALTER TABLE "public"."bus_geo_photo"
|
||||||
|
ADD CONSTRAINT "uav_mode_pkey" PRIMARY KEY ("id");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- 20260605 aros 蛙跳 by zhangchuang
|
-- 20260605 aros 蛙跳 by zhangchuang
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue