导入图像功能完成

This commit is contained in:
gaoxiong 2025-04-26 02:28:16 +08:00
parent 4a162a4eda
commit f37d16e195
17 changed files with 365 additions and 39 deletions

View File

@ -140,6 +140,17 @@
<artifactId>metadata-extractor</artifactId>
<version>2.15.0</version>
</dependency>
<!-- mapstruct驱动包 -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.1.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.1.Final</version>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -0,0 +1,25 @@
package com.dite.znpt.converts;
import com.dite.znpt.domain.entity.ImageCollectEntity;
import com.dite.znpt.domain.entity.ImageEntity;
import com.dite.znpt.domain.vo.ImageCollectReq;
import com.dite.znpt.domain.vo.ImageReq;
import org.mapstruct.Mapper;
import org.mapstruct.NullValuePropertyMappingStrategy;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* @Author: gaoxiong
* @Date: 2025/4/26 1:32
* @Description:
*/
@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
public interface Converts {
Converts INSTANCE = Mappers.getMapper(Converts.class);
List<ImageEntity> toImageEntity(List<ImageReq> list);
ImageCollectEntity toImageCollectEntity(ImageCollectReq req);
}

View File

@ -20,7 +20,6 @@ import java.util.List;
@AllArgsConstructor
@NoArgsConstructor
@Data
@SuperBuilder(toBuilder = true)
public class AuditableEntity implements Serializable {
private static final long serialVersionUID = 141481953116476081L;

View File

@ -29,9 +29,13 @@ public class ImageCollectEntity extends AuditableEntity implements Serializable
private static final long serialVersionUID = -2957687117182827156L;
@ApiModelProperty("图像采集id")
@TableId(value = "collect", type = IdType.ASSIGN_UUID)
@TableId(value = "collect_id", type = IdType.ASSIGN_UUID)
private String collectId;
@ApiModelProperty("部件id")
@TableField("part_id")
private String partId;
@ApiModelProperty("拍摄时间-起")
@TableField("shooting_time_begin")
private LocalDateTime shootingTimeBegin;
@ -64,10 +68,14 @@ public class ImageCollectEntity extends AuditableEntity implements Serializable
@TableField("shooting_method")
private String shootingMethod;
@ApiModelProperty("拍摄方式枚举ShootingDistanceEnum")
@ApiModelProperty("拍摄距离")
@TableField("shooting_distance")
private Integer shootingDistance;
@ApiModelProperty("采集员id")
@TableField("collector_id")
private String collectorId;
@ApiModelProperty("采集员姓名")
@TableField("collector_name")
private String collectorName;

View File

@ -36,18 +36,6 @@ public class ImageEntity extends AuditableEntity implements Serializable {
@TableField("collect_id")
private String collectId;
@ApiModelProperty("部件id")
@TableField("part_id")
private String partId;
@ApiModelProperty("项目id")
@TableField("project_id")
private String projectId;
@ApiModelProperty("机组id")
@TableField("turbine_id")
private String turbineId;
@ApiModelProperty("图像名称")
@TableField("image_name")
private String imageName;

View File

@ -0,0 +1,60 @@
package com.dite.znpt.domain.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
/**
* @Author: gaoxiong
* @Date: 2025/4/26 1:11
* @Description:
*/
@Data
@ApiModel("图像采集信息请求实体")
public class ImageCollectReq implements Serializable {
@Serial
private static final long serialVersionUID = 8937301872925896770L;
@ApiModelProperty("拍摄时间-起")
private LocalDateTime shootingTimeBegin;
@ApiModelProperty("拍摄时间-讫")
private LocalDateTime shootingTimeEnd;
@ApiModelProperty("天气,枚举WeatherEnum")
private String weather;
@ApiModelProperty("湿度(百分比)")
private Integer humidness;
@ApiModelProperty("温度-低")
private Double temperatureMin;
@ApiModelProperty("温度-高")
private Double temperatureMax;
@ApiModelProperty("风力等级")
private Integer windLevel;
@ApiModelProperty("拍摄方式枚举ShootingMethodEnum")
private String shootingMethod;
@ApiModelProperty("拍摄距离")
private Integer shootingDistance;
@ApiModelProperty("采集员id")
private String collectorId;
@ApiModelProperty("采集员姓名")
private String collectorName;
@ApiModelProperty("图像信息")
private List<ImageReq> imageList;
}

View File

@ -1,9 +1,19 @@
package com.dite.znpt.domain.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @Author: gaoxiong
* @Date: 2025/4/24 21:16
* @Description:
*/
public class ImageCollectResp {
@Data
@ApiModel("图像采集信息响应实体")
public class ImageCollectResp implements Serializable {
@Serial
private static final long serialVersionUID = 6594307991137605975L;
}

View File

@ -12,7 +12,7 @@ import java.io.Serializable;
* @description
*/
@Data
@ApiModel("图像信息列表查询实体")
@ApiModel("图像采集信息列表查询实体")
public class ImageListReq implements Serializable {
@Serial
private static final long serialVersionUID = 671014582625089979L;

View File

@ -0,0 +1,59 @@
package com.dite.znpt.domain.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @Author: gaoxiong
* @Date: 2025/4/26 1:18
* @Description:
*/
@Data
@ApiModel("图像信息请求实体")
public class ImageReq implements Serializable {
@Serial
private static final long serialVersionUID = -1726859254176864573L;
@ApiModelProperty("图像id")
private String imageId;
@ApiModelProperty("图像名称")
@TableField("image_name")
private String imageName;
@ApiModelProperty("图像尺寸")
private String imageSize;
@ApiModelProperty("焦距")
private String focalDistance;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("拍摄时间")
private LocalDateTime shootingTime;
@ApiModelProperty("相机制造商")
private String cameraManufacturer;
@ApiModelProperty("相机型号")
private String cameraModel;
@ApiModelProperty("经度")
private String longitude;
@ApiModelProperty("纬度")
private String latitude;
@ApiModelProperty("海拔")
private String altitude;
@ApiModelProperty("图片路径")
private String imagePath;
}

View File

@ -1,10 +1,14 @@
package com.dite.znpt.domain.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author Bear.G
@ -13,7 +17,10 @@ import java.io.Serializable;
*/
@Data
@ApiModel("图像信息响应实体")
public class ImageResp implements Serializable {
public class ImageResp extends ImageReq implements Serializable {
@Serial
private static final long serialVersionUID = -5215414858454232077L;
@ApiModelProperty("影像类型枚举ImageTypeEnum")
private String imageType;
}

View File

@ -2,6 +2,7 @@ package com.dite.znpt.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dite.znpt.domain.entity.ImageCollectEntity;
import com.dite.znpt.domain.vo.ImageCollectReq;
/**
* @Author: gaoxiong
@ -9,4 +10,5 @@ import com.dite.znpt.domain.entity.ImageCollectEntity;
* @Description:
*/
public interface ImageCollectService extends IService<ImageCollectEntity> {
void save(String departId, ImageCollectReq req);
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.dite.znpt.domain.entity.ImageEntity;
import com.dite.znpt.domain.vo.ImageListReq;
import com.dite.znpt.domain.vo.ImageResp;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@ -15,4 +16,6 @@ import java.util.List;
public interface ImageService extends IService<ImageEntity> {
List<ImageResp> selectList(ImageListReq req);
List<ImageResp> batchUpload(String departId, MultipartFile[] files);
}

View File

@ -1,10 +1,22 @@
package com.dite.znpt.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dite.znpt.converts.Converts;
import com.dite.znpt.domain.entity.ImageCollectEntity;
import com.dite.znpt.domain.entity.ImageEntity;
import com.dite.znpt.domain.vo.ImageCollectReq;
import com.dite.znpt.mapper.ImageCollectMapper;
import com.dite.znpt.service.ImageCollectService;
import com.dite.znpt.service.ImageService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.File;
import java.util.List;
/**
* @Author: gaoxiong
@ -14,4 +26,33 @@ import org.springframework.stereotype.Service;
@Service
public class ImageCollectServiceImpl extends ServiceImpl<ImageCollectMapper, ImageCollectEntity> implements ImageCollectService {
@Value("${upload.perm-path}")
private String permPath;
@Resource
private ImageService imageService;
@Transactional(rollbackFor = Exception.class)
@Override
public void save(String partId, ImageCollectReq req) {
ImageCollectEntity imageCollect = Converts.INSTANCE.toImageCollectEntity(req);
imageCollect.setPartId(partId);
this.save(imageCollect);
List<ImageEntity> imageList = Converts.INSTANCE.toImageEntity(req.getImageList());
String path_prefix = permPath.concat(StrUtil.BACKSLASH).concat(partId).concat(StrUtil.BACKSLASH);
imageList.stream().forEach(image -> {
image.setCollectId(imageCollect.getCollectId());
String path = path_prefix + image.getImageName();
File file = new File(image.getImagePath());
if (file.exists()) {
byte[] bytes = FileUtil.readBytes(file);
FileUtil.writeBytes(bytes, path);
FileUtil.del(file);
image.setImagePath(path);
}else {
imageList.remove(image);
}
});
imageService.saveOrUpdateBatch(imageList);
}
}

View File

@ -1,15 +1,32 @@
package com.dite.znpt.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dite.znpt.domain.entity.ImageEntity;
import com.dite.znpt.domain.vo.ImageListReq;
import com.dite.znpt.domain.vo.ImageResp;
import com.dite.znpt.mapper.ImageMapper;
import com.dite.znpt.service.ImageService;
import com.dite.znpt.util.EXIFUtil;
import com.dite.znpt.util.PageUtil;
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 java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Bear.G
@ -18,6 +35,10 @@ import java.util.List;
*/
@Service
public class ImageServiceImpl extends ServiceImpl<ImageMapper, ImageEntity> implements ImageService {
@Value("${upload.temp-path}")
private String tempPath;
@Override
public List<ImageResp> selectList(ImageListReq req) {
PageUtil.startPage();
@ -27,4 +48,65 @@ public class ImageServiceImpl extends ServiceImpl<ImageMapper, ImageEntity> impl
});
return imageList;
}
@Transactional(rollbackFor = Exception.class)
@Override
public List<ImageResp> batchUpload(String departId, MultipartFile[] files) {
List<ImageResp> list = new ArrayList<>(files.length);
String path_prefix = tempPath.concat(StrUtil.BACKSLASH).concat(departId).concat(StrUtil.BACKSLASH);
for (MultipartFile file : files) {
if (!file.isEmpty()) {
try {
String path = path_prefix + file.getOriginalFilename();
FileUtil.writeBytes(file.getBytes(),path);
list.add(imageRespBuilder(path));
} catch (Exception e) {
e.printStackTrace();
}
}
}
return list;
}
private ImageResp imageRespBuilder(String path) throws Exception {
ImageResp resp = new ImageResp();
File file = new File(path);
JSONObject obj = EXIFUtil.printImageTags(file);
resp.setCameraManufacturer(obj.getStr("Make"));
resp.setCameraModel(obj.getStr("Model"));
resp.setImageName(obj.getStr("File Name"));
resp.setImagePath(path);
resp.setImageSize(extractDigit(obj.getStr("Image Width")).concat("*").concat(extractDigit(obj.getStr("Image Height"))));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy:MM:dd HH:mm:ss");
resp.setShootingTime(LocalDateTime.parse( obj.getStr("Date/Time Original"),formatter));
resp.setFocalDistance(extractDigit(obj.getStr("Focal Length")));
resp.setLatitude(obj.getStr("GPS Latitude").concat("°").concat(directionTranslator(obj.getStr("GPS Latitude Ref"))));
resp.setLongitude(obj.getStr("GPS Longitude").concat("°").concat(directionTranslator(obj.getStr("GPS Longitude Ref"))));
resp.setAltitude(extractDigit(obj.getStr("GPS Altitude")).concat("m"));
return resp;
}
private String directionTranslator(String direction){
if(direction.equalsIgnoreCase("N")){
return "";
} else if (direction.equalsIgnoreCase("S")) {
return "";
} else if (direction.equalsIgnoreCase("E")) {
return "";
}else if (direction.equalsIgnoreCase("W")) {
return "西";
}else {
return "未知";
}
}
private static String extractDigit(String str) {
Pattern pattern = Pattern.compile("\\d+(\\.\\d+)?");
Matcher matcher = pattern.matcher(str);
if (matcher.find()) {
return matcher.group();
} else {
return null;
}
}
}

View File

@ -0,0 +1,33 @@
package com.dite.znpt.web.controller;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.vo.ImageCollectReq;
import com.dite.znpt.domain.vo.ImageResp;
import com.dite.znpt.service.ImageCollectService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.List;
/**
* @Author: gaoxiong
* @Date: 2025/4/26 1:34
* @Description:
*/
@Api(tags = "图像采集信息")
@RestController
@RequestMapping("/image-collect")
public class ImageCollectController {
@Resource
private ImageCollectService imageCollectService;
@ApiOperation(value = "保存图像采集信息", httpMethod = "POST")
@PostMapping("/{departId}")
public Result save(@PathVariable String departId, @RequestBody ImageCollectReq req) {
imageCollectService.save(departId, req);
return Result.ok();
}
}

View File

@ -2,6 +2,7 @@ package com.dite.znpt.web.controller;
import com.dite.znpt.domain.PageResult;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.vo.ImageListReq;
import com.dite.znpt.domain.vo.ImageResp;
import com.dite.znpt.service.ImageService;
@ -39,19 +40,7 @@ public class ImageController {
@ApiOperation(value = "批量上传图像", httpMethod = "POST")
@PostMapping("/upload-batch/{departId}")
public List uploadBatch(@PathVariable String departId, @RequestParam("files") MultipartFile[] files) {
for (MultipartFile file : files) {
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
java.nio.file.Path path = Paths.get("G:\\Image/" + file.getOriginalFilename());
Files.write(path, bytes);
System.out.println("Uploaded: " + file.getOriginalFilename());
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
public Result<List<ImageResp>> uploadBatch(@PathVariable String departId, @RequestParam("files") MultipartFile[] files) {
return Result.ok(imageService.batchUpload(departId, files));
}
}

View File

@ -1,7 +1,7 @@
# 开发环境配置
server:
# 服务器的HTTP端口默认为8080
port: 8080
port: 8888
# 数据源配置
spring:
@ -10,7 +10,7 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://39.99.201.243:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: h67&E98HS8^6
password: BUw8YW6%@^8q
druid:
# 初始连接数
initialSize: 5
@ -59,11 +59,15 @@ spring:
max-wait: 3000
host: 39.99.201.243
port: 6379
password: yfeng@123
password: diTeZn@123
timeout: 3000
# 0 gaea系统3 gaea-dev/gaea-test系统4 znpt开发5 znpt测试 6 znpt生产
database: 4
rabbitmq:
host: 39.99.201.243
port: 3389
username: dite
password: diTezN@123
## MINIO配置
#minio:
# url: http://10.20.32.11:9000
@ -80,7 +84,7 @@ spring:
sip-config:
name: 信令服务
ip: 10.17.12.203
ip: 127.0.0.1
port: 1074
charset: gb2312
domain: 3402000000
@ -96,7 +100,7 @@ zlm-config:
# 公网ip
publicHost:
# 接口ip
apiHost: 10.17.12.203
apiHost: 127.0.0.1
# 接口端口
apiPort: 30186
# 密钥
@ -104,10 +108,15 @@ zlm-config:
# 流id前缀
streamPrefix:
# rtp ip
rtpHost: 10.17.12.203
rtpHost: 127.0.0.1
# rtp 端口
rtpPort: 30186
# 动态端口起始值
dynamicPortStart: 30150
# 动态端口结束值
dynamicPortEnd: 30185
upload:
temp-path: D:\Upload\Temp
perm-path: D:\Upload\Perm