新增接口

This commit is contained in:
haozq 2025-07-03 18:51:03 +08:00
parent 96112fb21a
commit c341a76ea0
17 changed files with 1542 additions and 26 deletions

View File

@ -15,7 +15,11 @@
</description>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.2</version>
</dependency>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
@ -48,7 +52,11 @@
<artifactId>swagger-models</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.5.6</version>
</dependency>
<!-- Mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>

View File

@ -159,6 +159,8 @@ public class RobotController extends BaseController {
return service.addVideoFile(multipartFile,puid);
}
/**
* 查询录音文件
* @param vo

View File

@ -0,0 +1,64 @@
package com.bonus.business.mongodb.config;
import com.bonus.common.utils.StringUtils;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author coisini
* @version 1.0
* @Description MongoDB配置类
* @date Apr 17, 2022
*/
@Configuration
public class MongoConfig {
/**
* 数据库配置信息
*/
@Value("${spring.data.mongodb.database}")
private String db;
@Value("${spring.data.mongodb.host}")
private String host;
@Value("${spring.data.mongodb.port}")
private Integer port;
@Value("${spring.data.mongodb.username}")
private String UN ;
@Value("${spring.data.mongodb.password}")
private String PD ;
private MongoDatabase mongoDatabase;
public MongoClient getMongoClient() {
String addr;
if(StringUtils.isEmpty(UN)){
addr = "mongodb://" + host + ":" + port;
}else{
addr = "mongodb://" + UN + ":" + PD + "@" + host + ":" + port + "/" + db;
}
return MongoClients.create(addr);
}
public MongoDatabase getMongoConn() {
MongoClient mongoClient = getMongoClient();
mongoDatabase = mongoClient.getDatabase(db);
System.err.println("mongodb开始初始化");
return mongoDatabase;
}
@Bean
public GridFSBucket getGridFsBucket() {
MongoDatabase mongoDatabase = getMongoConn();
return GridFSBuckets.create(mongoDatabase);
}
}

View File

@ -0,0 +1,16 @@
package com.bonus.business.mongodb.config;
import com.bonus.business.mongodb.model.MongoFile;
import org.springframework.data.mongodb.repository.MongoRepository;
/**
* @author coisini
* @version 1.0
* @Description MongoDB文件仓储
* @date Apr 17, 2022
*/
public interface MongoFileRepository extends MongoRepository<MongoFile, String> {
}

View File

@ -0,0 +1,70 @@
package com.bonus.business.mongodb.model;
import lombok.Builder;
import lombok.Data;
import org.bson.types.Binary;
import org.springframework.data.annotation.Id;
/**
* @author coisini
* @version 1.0
* @Description MongoDB文件实体
* @date Apr 17, 2022
*/
@Builder
@Data
public class MongoFile {
/**
* 主键
*/
@Id
public String id;
/**
* 文件名称
*/
public String fileName;
/**
* 文件大小
*/
public long fileSize;
/**
* 上传时间
*/
public String uploadDate;
/**
* MD5值
*/
public String md5;
/**
* 文件内容
*/
private Binary content;
/**
* 文件类型
*/
public String contentType;
/**
* 文件后缀名
*/
public String suffix;
/**
* 文件描述
*/
public String description;
/**
* 大文件管理GridFS的ID
*/
private String gridFsId;
}

View File

@ -0,0 +1,78 @@
package com.bonus.business.mongodb.model;
/**
* @author coisini
* @version 1.0
* @Description 统一消息
* @date Apr 17, 2022
*/
public class ResponseMessage<T> {
private String status;
private String message;
private T data;
public static ResponseMessage<?> ok() {
return create("0", (String) null, (Object) null);
}
public static ResponseMessage<?> ok(String message) {
return create("0", message, (Object) null);
}
public static <T> ResponseMessage<T> ok(String message, T data) {
return create("0", message, data);
}
public static <T> ResponseMessage<T> ok(T data) {
return create("0", (String) null, data);
}
public static ResponseMessage<?> error() {
return create("1", (String) null, (Object) null);
}
public static ResponseMessage<?> error(String message) {
return create("1", message, (Object) null);
}
public static <T> ResponseMessage<T> error(String message, T data) {
return create("1", message, data);
}
private static <T> ResponseMessage<T> create(String status, String message, T data) {
ResponseMessage<T> t = new ResponseMessage();
t.setStatus(status);
t.setMessage(message);
t.setData(data);
return t;
}
public ResponseMessage() {
}
public String getStatus() {
return this.status;
}
public String getMessage() {
return this.message;
}
public T getData() {
return this.data;
}
public void setStatus(final String status) {
this.status = status;
}
public void setMessage(final String message) {
this.message = message;
}
public void setData(final T data) {
this.data = data;
}
}

View File

@ -0,0 +1,333 @@
package com.bonus.business.mongodb.service;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import com.bonus.business.mongodb.config.MongoFileRepository;
import com.bonus.business.mongodb.model.MongoFile;
import com.bonus.business.mongodb.vo.FileExportVo;
import com.bonus.business.robot.util.Md5Util;
import com.bonus.common.utils.DateUtils;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.Binary;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* @author coisini
* @version 1.0
* @Description MongoDB文件上传实现类
* @date Apr 17, 2022
*/
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class FileMongoServiceImpl {
private final MongoFileRepository mongoFileRepository;
private final MongoTemplate mongoTemplate;
private final GridFsTemplate gridFsTemplate;
private final GridFSBucket gridFSBucket;
private static final int MAX_SIZE = 16777216;
private static final String SUFFIX = ".";
/**
* 多文件上传
*
* @param files
* @return
*/
public List<FileExportVo> uploadFiles(List<MultipartFile> files) {
return files.stream().map(file -> {
try {
return this.uploadFile(file);
} catch (Exception e) {
log.error("文件上传失败", e);
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
}
/**
* 文件上传
*
* @param file
* @return
* @throws Exception
*/
public FileExportVo uploadFile(MultipartFile file) throws Exception {
if (file.getSize() > MAX_SIZE) {
return this.saveGridFsFile(file);
} else {
return this.saveBinaryFile(file);
}
}
public FileExportVo uploadFile(File file) throws Exception {
if (file.length() > MAX_SIZE) {
return this.saveGridFsFile(file);
} else {
return this.saveBinaryFile(file);
}
}
/**
* 文件下载
*
* @param fileId
* @return
*/
public FileExportVo downloadFile(String fileId) {
Optional<MongoFile> option = this.getBinaryFileById(fileId);
if (option.isPresent()) {
MongoFile mongoFile = option.get();
if (Objects.isNull(mongoFile.getContent())) {
option = this.getGridFsFileById(fileId);
}
}
return option.map(FileExportVo::new).orElse(null);
}
/**
* 文件删除
*
* @param fileId
*/
public void removeFile(String fileId) {
Optional<MongoFile> option = this.getBinaryFileById(fileId);
if (option.isPresent()) {
if (Objects.nonNull(option.get().getGridFsId())) {
this.removeGridFsFile(fileId);
} else {
this.removeBinaryFile(fileId);
}
}
}
/**
* 删除Binary文件
*
* @param fileId
*/
public void removeBinaryFile(String fileId) {
mongoFileRepository.deleteById(fileId);
}
/**
* 删除GridFs文件
*
* @param fileId
*/
public void removeGridFsFile(String fileId) {
// TODO 根据id查询文件
MongoFile mongoFile = mongoTemplate.findById(fileId, MongoFile.class);
if (Objects.nonNull(mongoFile)) {
// TODO 根据文件ID删除fs.files和fs.chunks中的记录
Query deleteFileQuery = new Query().addCriteria(Criteria.where("filename").is(mongoFile.getGridFsId()));
gridFsTemplate.delete(deleteFileQuery);
// TODO 删除集合mongoFile中的数据
Query deleteQuery = new Query(Criteria.where("id").is(fileId));
mongoTemplate.remove(deleteQuery, MongoFile.class);
}
}
/**
* 保存Binary文件小文件
*
* @param file
* @return
* @throws Exception
*/
public FileExportVo saveBinaryFile(MultipartFile file) throws Exception {
String suffix = getFileSuffix(file);
MongoFile mongoFile = mongoFileRepository.save(
MongoFile.builder()
.fileName(file.getOriginalFilename())
.fileSize(file.getSize())
.content(new Binary(file.getBytes()))
.contentType(file.getContentType())
.uploadDate(DateUtils.dateTimeNow())
.suffix(suffix)
.md5(Md5Util.getMd5(file.getInputStream()))
.build()
);
return new FileExportVo(mongoFile);
}
/**
* 保存GridFs文件大文件
*
* @param file
* @return
* @throws Exception
*/
public FileExportVo saveGridFsFile(MultipartFile file) throws Exception {
String suffix = getFileSuffix(file);
String gridFsId = this.storeFileToGridFs(file.getInputStream(), file.getContentType());
MongoFile mongoFile = mongoTemplate.save(
MongoFile.builder()
.fileName(file.getOriginalFilename())
.fileSize(file.getSize())
.contentType(file.getContentType())
.uploadDate(DateUtils.dateTimeNow())
.suffix(suffix)
.md5(Md5Util.getMd5(file.getInputStream()))
.gridFsId(gridFsId)
.build()
);
return new FileExportVo(mongoFile);
}
public FileExportVo saveBinaryFile(File file) throws Exception {
String suffix = getFileSuffix(file);
Path path = Paths.get(file.getPath());
String contentType = Files.probeContentType(path);
FileInputStream inputStream = new FileInputStream(file);
// 创建一个与文件大小相等的字节数组
byte[] fileContent = new byte[(int) file.length()];
try (FileInputStream fis = new FileInputStream(file)) {
// 读取文件内容到字节数组
fis.read(fileContent);
} catch (IOException e) {
e.printStackTrace();
}
MongoFile mongoFile = mongoFileRepository.save(
MongoFile.builder()
.fileName(file.getName())
.fileSize(file.length())
.content(new Binary(fileContent))
.contentType(contentType)
.uploadDate(DateUtils.dateTimeNow())
.suffix(suffix)
.md5(Md5Util.getMd5(inputStream))
.build()
);
return new FileExportVo(mongoFile);
}
public FileExportVo saveGridFsFile(File file) throws Exception {
String suffix = getFileSuffix(file);
Path path = Paths.get(file.getPath());
String contentType = Files.probeContentType(path);
FileInputStream inputStream = new FileInputStream(file);
String gridFsId = this.storeFileToGridFs(inputStream, contentType);
MongoFile mongoFile = mongoTemplate.save(
MongoFile.builder()
.fileName(file.getName())
.fileSize(file.length())
.contentType(contentType)
.uploadDate(DateUtils.dateTimeNow())
.suffix(suffix)
.md5(Md5Util.getMd5(inputStream))
.gridFsId(gridFsId)
.build()
);
return new FileExportVo(mongoFile);
}
/**
* 上传文件到Mongodb的GridFs中
*
* @param in
* @param contentType
* @return
*/
public String storeFileToGridFs(InputStream in, String contentType) {
String gridFsId = IdUtil.simpleUUID();
// TODO 将文件存储进GridFS中
gridFsTemplate.store(in, gridFsId, contentType);
return gridFsId;
}
/**
* 获取Binary文件
*
* @param id
* @return
*/
public Optional<MongoFile> getBinaryFileById(String id) {
return mongoFileRepository.findById(id);
}
/**
* 获取Grid文件
*
* @param id
* @return
*/
public Optional<MongoFile> getGridFsFileById(String id) {
MongoFile mongoFile = mongoTemplate.findById(id, MongoFile.class);
if (Objects.nonNull(mongoFile)) {
Query gridQuery = new Query().addCriteria(Criteria.where("filename").is(mongoFile.getGridFsId()));
try {
// TODO 根据id查询文件
GridFSFile fsFile = gridFsTemplate.findOne(gridQuery);
// TODO 打开流下载对象
GridFSDownloadStream in = gridFSBucket.openDownloadStream(fsFile.getObjectId());
if (in.getGridFSFile().getLength() > 0) {
// TODO 获取流对象
GridFsResource resource = new GridFsResource(fsFile, in);
// TODO 获取数据
mongoFile.setContent(new Binary(IoUtil.readBytes(resource.getInputStream())));
return Optional.of(mongoFile);
} else {
return Optional.empty();
}
} catch (IOException e) {
log.error("获取MongoDB大文件失败", e);
}
}
return Optional.empty();
}
/**
* 获取文件后缀
*
* @param file
* @return
*/
private String getFileSuffix(MultipartFile file) {
String suffix = "";
if (Objects.requireNonNull(file.getOriginalFilename()).contains(SUFFIX)) {
suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
}
return suffix;
}
private String getFileSuffix(File file) {
String suffix = "";
String fileName = file.getName();
return fileName.substring( fileName.lastIndexOf("."));
}
}

View File

@ -0,0 +1,80 @@
package com.bonus.business.mongodb.service;
import com.bonus.business.mongodb.utils.MongodbFileUtil;
import com.bonus.business.mongodb.vo.FileExportVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.TempFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
@Slf4j
@Service
public class FileService {
@Autowired
private FileMongoServiceImpl fileMongoService;
/**
* 文件上传到mongodb
* @param multipartFile
* @return
* @throws Exception
*/
public String uploadFile(MultipartFile multipartFile) throws Exception {
FileExportVo vo= fileMongoService.uploadFile(multipartFile);
return vo.getFileId();
}
/**
* 文件上次
* @param file
* @return
* @throws Exception
*/
public String uploadFile(File file) throws Exception {
FileExportVo vo= fileMongoService.uploadFile(file);
return vo.getFileId();
}
/**
* 文件下载转换成bast64
* @param fileId
* @return
*/
public String downloadFile(String fileId){
FileExportVo vo5= fileMongoService.downloadFile(fileId);
return MongodbFileUtil.getBase64File(vo5);
}
public FileExportVo getFileInfo(String fileId){
return fileMongoService.downloadFile(fileId);
}
/**
* 文件下载转换成bast64
* @param fileId
* @return
*/
public byte[] getFileByte(String fileId){
FileExportVo vo5= fileMongoService.downloadFile(fileId);
return vo5.getData();
}
/**
* 删除文件
* @param fileId
* @return
*/
public void delData(String fileId){
fileMongoService.removeFile(fileId);
}
}

View File

@ -0,0 +1,70 @@
package com.bonus.business.mongodb.utils;
import com.bonus.business.mongodb.vo.FileExportVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Base64Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Base64Utils;
import javax.annotation.Resource;
import java.util.Objects;
/**
* @authorcwchen
* @date2024-03-11-15:55
* @version1.0
* @descriptionmongodb文件上传-工具类
*/
@Slf4j
public class MongodbFileUtil {
/**
* 获取文件的base64地址
*
* @param vo
* @return String
* @description
* @author cwchen
* @date 2024/3/12 11:00
*/
public static String getBase64(FileExportVo vo) {
try {
byte[] bytes = vo.getData();
if (!Objects.isNull(bytes)) {
String suffix = vo.getSuffix().replace(".", "");
return "data:image/" + suffix + ";base64," + Base64Utils.encodeToString(bytes);
}
} catch (Exception e) {
log.error("byte流转base64", e);
}
return null;
}
/**
* 获取文件的base64地址
*
* @param vo
* @return String
* @description
* @author cwchen
* @date 2024/3/12 11:00
*/
public static String getBase64File(FileExportVo vo) {
try {
byte[] bytes = vo.getData();
if (!Objects.isNull(bytes)) {
String suffix = vo.getSuffix().replace(".", "");
return Base64Utils.encodeToString(bytes);
}
} catch (Exception e) {
log.error("byte流转base64", e);
}
return null;
}
}

View File

@ -0,0 +1,60 @@
package com.bonus.business.mongodb.vo;
import cn.hutool.core.bean.BeanUtil;
import com.bonus.business.mongodb.model.MongoFile;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import java.io.Serializable;
import java.util.Objects;
/**
* @author lit@epsoft.com.cn
* @version 1.0
* @Description 统一文件下载vo
* @date Apr 8, 2022
*/
@Data
public class FileExportVo implements Serializable {
private String file;
private String fileId;
private String fileName;
private String contentType;
private String suffix;
private long fileSize;
private String sourceId;
private String id;
private String fileType;
/**
* 资源类型
*/
private String sourceType;
private String updaetTime;
@JsonIgnore
private byte[] data;
public FileExportVo() {
}
public FileExportVo(MongoFile mongoFile) {
BeanUtil.copyProperties(mongoFile, this);
if (Objects.nonNull(mongoFile.getContent())) {
this.data = mongoFile.getContent().getData();
}
this.fileId = mongoFile.getId();
}
}

View File

@ -0,0 +1,60 @@
package com.bonus.business.robot.util;
/**
* ID生成器工具类
*
* @author czc
*/
public class IdUtils
{
/**
* 获取随机UUID
*
* @return 随机UUID
*/
public static String randomuuid()
{
return UUID.randomuuid().toString();
}
/**
* 简化的UUID去掉了横线
*
* @return 简化的UUID去掉了横线
*/
public static String simpleuuid()
{
return UUID.randomuuid().toString(true);
}
/**
* 简化的UUID去掉了横线
*
* @return 简化的UUID去掉了横线
*/
public static String getuid()
{
return UUID.randomuuid().toString(true).toUpperCase();
}
/**
* 获取随机UUID使用性能更好的ThreadLocalRandom生成UUID
*
* @return 随机UUID
*/
public static String fastuuid()
{
return UUID.fastuuid().toString();
}
/**
* 简化的UUID去掉了横线使用性能更好的ThreadLocalRandom生成UUID
*
* @return 简化的UUID去掉了横线
*/
public static String fastsimpleuuid()
{
return UUID.fastuuid().toString(true);
}
}

View File

@ -0,0 +1,134 @@
package com.bonus.business.robot.util;
import com.bonus.common.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class ImageResizer {
public static void main(String[] args) {
try {
// 读取PNG图片
BufferedImage pngImage = ImageIO.read(new File("F:\\files\\robot\\userImage\\2025\\07\\01\\test3.png"));
// 创建一个新的BufferedImage对象设置其类型为TYPE_INT_RGB
BufferedImage jpgImage = new BufferedImage(pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_INT_RGB);
// 绘制PNG图片到jpgImage
jpgImage.createGraphics().drawImage(pngImage, 0, 0, Color.WHITE, null);
ImageIO.write(jpgImage, "jpg", new File("F:\\files\\robot\\userImage\\2025\\07\\01\\test8.jpg"));
File inputFile = new File("F:\\files\\robot\\userImage\\2025\\07\\01\\test3.png");
BufferedImage originalImage = ImageIO.read(inputFile);
System.out.println("Original Image Size: " + originalImage.getWidth() + "x" + originalImage.getHeight());
// *
int targetWidth = 1080;
// 新高度
int targetHeight = 800;
BufferedImage resizedImage = resizeImage(originalImage, targetWidth, targetHeight);
System.out.println("Resized Image Size: " + resizedImage.getWidth() + "x" + resizedImage.getHeight());
// 保存为PNG格式
saveImage(resizedImage, "jpg", "F:\\files\\robot\\userImage\\2025\\07\\01\\test6.jpg");
} catch (IOException e) {
e.printStackTrace();
}
}
public static List<String> fileType = new ArrayList<>();
/**
* 获取文件->最终转成 本地临时文件使用完必须删除
* @param
* @return
*/
public static String transImageByJpg(String filePath,byte[] bytes,String suffix){
try{
String roundId=IdUtils.randomuuid();
String path="/temp/";
File folder = new File(filePath+path);
if (folder.exists() && folder.isDirectory()) {
System.out.println("文件夹存在");
} else {
folder.mkdir();
System.out.println("文件夹不存在");
}
// 创建临时文件确保文件名具有唯一性
File file = File.createTempFile(filePath+path+roundId, suffix);
// 将字节数据写入文件
FileOutputStream fos = new FileOutputStream(file);
fos.write(bytes);
fos.close();
String newJpgPath=null;
//不是jpg的先转成jpg的
getFileType();
if (!fileType.contains(suffix)){
String roundId2=IdUtils.randomuuid();
//jpg的路径
newJpgPath=filePath+path+roundId2+".jpg";
BufferedImage pngImage = ImageIO.read(file);
BufferedImage jpgImage = new BufferedImage(pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_INT_RGB);
// 绘制PNG图片到jpgImage
jpgImage.createGraphics().drawImage(pngImage, 0, 0, Color.WHITE, null);
ImageIO.write(jpgImage, "jpg", new File(newJpgPath));
}
//
File inputFile;
//是jpg格式的
if(newJpgPath==null){
inputFile=file;
}else{
inputFile = new File(newJpgPath);
}
BufferedImage originalImage = ImageIO.read(inputFile);
BufferedImage resizedImage = resizeImage(originalImage, 1080, 800);
// 保存为PNG格式
String roundId3=IdUtils.randomuuid();
String lastPath=filePath+path+roundId3+".jpg";
saveImage(resizedImage, "jpg", lastPath);
if(newJpgPath!=null){
boolean isde=new File(newJpgPath).delete();
System.err.println("删除->"+isde);
}
boolean delete=file.delete();
System.err.println("删除->"+delete);
return lastPath;
}catch (Exception e){
log.error(e.toString(),e);
}
return null;
}
public static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) {
BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, originalImage.getType());
Graphics2D graphics2D = resizedImage.createGraphics();
graphics2D.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);
graphics2D.dispose();
return resizedImage;
}
public static void saveImage(BufferedImage resizedImage, String format, String outputPath) throws IOException {
File outputFile = new File(outputPath);
ImageIO.write(resizedImage, format, outputFile);
}
public static void getFileType(){
fileType.add("jpg");
fileType.add("JPG");
fileType.add(".JPG");
fileType.add(".jpg");
}
}

View File

@ -0,0 +1,36 @@
package com.bonus.business.robot.util;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* @author 10488
* @version 1.0
* @Description MD5工具类
* @date Apr 8, 2022
*/
public class Md5Util {
/**
* 获取该输入流的MD5值
*/
public static String getMd5(InputStream is) throws NoSuchAlgorithmException, IOException {
StringBuffer md5 = new StringBuffer();
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = is.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
}
;
byte[] mdbytes = md.digest();
// convert the byte to hex format
for (int i = 0; i < mdbytes.length; i++) {
md5.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
return md5.toString();
}
}

View File

@ -0,0 +1,489 @@
package com.bonus.business.robot.util;
import com.bonus.common.exception.UtilException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
/**
* 提供通用唯一识别码universally unique identifierUUID实现
*
* @author czc
*/
public final class UUID implements java.io.Serializable, Comparable<UUID>
{
private static final long serialVersionUID = -1185015143654744140L;
/**
* SecureRandom 的单例
*
*/
private static class Holder
{
static final SecureRandom NUMBER_GENERATOR= getSecureRandom();
}
/** 此UUID的最高64有效位 */
private final long mostSigBits;
/** 此UUID的最低64有效位 */
private final long leastSigBits;
/**
* 私有构造
*
* @param data 数据
*/
private UUID(byte[] data)
{
long msb = 0;
long lsb = 0;
int max=8;
int max1=16;
assert data.length == 16 : "data must be 16 bytes in length";
for (int i = 0; i < max; i++)
{
msb = (msb << max) | (data[i] & 0xff);
}
for (int i = max; i < max1; i++)
{
lsb = (lsb << max) | (data[i] & 0xff);
}
this.mostSigBits = msb;
this.leastSigBits = lsb;
}
/**
* 使用指定的数据构造新的 UUID
*
* @param mostSigBits 用于 {@code UUID} 的最高有效 64
* @param leastSigBits 用于 {@code UUID} 的最低有效 64
*/
public UUID(long mostSigBits, long leastSigBits)
{
this.mostSigBits = mostSigBits;
this.leastSigBits = leastSigBits;
}
/**
* 获取类型 4伪随机生成的UUID 的静态工厂 使用加密的本地线程伪随机数生成器生成该 UUID
*
* @return 随机生成的 {@code UUID}
*/
public static UUID fastuuid()
{
return randomuuid(false);
}
/**
* 获取类型 4伪随机生成的UUID 的静态工厂 使用加密的强伪随机数生成器生成该 UUID
*
* @return 随机生成的 {@code UUID}
*/
public static UUID randomuuid()
{
return randomuuid(true);
}
/**
* 获取类型 4伪随机生成的UUID 的静态工厂 使用加密的强伪随机数生成器生成该 UUID
*
* @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码否则可以得到更好的性能
* @return 随机生成的 {@code UUID}
*/
public static UUID randomuuid(boolean isSecure)
{
final Random ng = isSecure ? Holder.NUMBER_GENERATOR : getRandom();
byte[] randomBytes = new byte[16];
ng.nextBytes(randomBytes);
randomBytes[6] &= 0x0f;
randomBytes[6] |= 0x40;
randomBytes[8] &= 0x3f;
randomBytes[8] |= 0x80;
return new UUID(randomBytes);
}
/**
* 根据指定的字节数组获取类型 3基于名称的UUID 的静态工厂
*
* @param name 用于构造 UUID 的字节数组
*
* @return 根据指定数组生成的 {@code UUID}
*/
public static UUID nameuuidfrombytes(byte[] name)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("MD5");
}
catch (NoSuchAlgorithmException nsae)
{
throw new InternalError("MD5 not supported");
}
byte[] md5Bytes = md.digest(name);
md5Bytes[6] &= 0x0f;
md5Bytes[6] |= 0x30;
md5Bytes[8] &= 0x3f;
md5Bytes[8] |= 0x80;
return new UUID(md5Bytes);
}
/**
* 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}
*
* @param name 指定 {@code UUID} 字符串
* @return 具有指定值的 {@code UUID}
* @throws IllegalArgumentException 如果 name {@link #toString} 中描述的字符串表示形式不符抛出此异常
*
*/
public static UUID fromString(String name)
{
String[] components = name.split("-");
int len5=5;
if (components.length != len5)
{
throw new IllegalArgumentException("Invalid UUID string: " + name);
}
StringBuilder scrub=new StringBuilder("0x");
for (int i = 0; i < len5; i++)
{
components[i] =scrub.append(components[i]).toString();
}
long mostSigBits = Long.decode(components[0]).longValue();
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[1]).longValue();
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[2]).longValue();
long leastSigBits = Long.decode(components[3]).longValue();
leastSigBits <<= 48;
leastSigBits |= Long.decode(components[4]).longValue();
return new UUID(mostSigBits, leastSigBits);
}
/**
* 返回此 UUID 128 位值中的最低有效 64
*
* @return UUID 128 位值中的最低有效 64
*/
public long getLeastSignificantBits()
{
return leastSigBits;
}
/**
* 返回此 UUID 128 位值中的最高有效 64
*
* @return UUID 128 位值中最高有效 64
*/
public long getMostSignificantBits()
{
return mostSigBits;
}
/**
* 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的
* <p>
* 版本号具有以下含意:
* <ul>
* <li>1 基于时间的 UUID
* <li>2 DCE 安全 UUID
* <li>3 基于名称的 UUID
* <li>4 随机生成的 UUID
* </ul>
*
* @return {@code UUID} 的版本号
*/
public int version()
{
// Version is bits masked by 0x000000000000F000 in MS long
return (int) ((mostSigBits >> 12) & 0x0f);
}
/**
* 与此 {@code UUID} 相关联的变体号变体号描述 {@code UUID} 的布局
* <p>
* 变体号具有以下含意
* <ul>
* <li>0 NCS 向后兼容保留
* <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF&nbsp;RFC&nbsp;4122</a>(Leach-Salz), 用于此类
* <li>6 保留微软向后兼容
* <li>7 保留供以后定义使用
* </ul>
*
* @return {@code UUID} 相关联的变体号
*/
public int variant()
{
// This field is composed of a varying number of bits.
// 0 - - Reserved for NCS backward compatibility
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
// 1 1 0 Reserved, Microsoft backward compatibility
// 1 1 1 Reserved for future definition.
return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
}
/**
* 与此 UUID 相关联的时间戳值
*
* <p>
* 60 位的时间戳值根据此 {@code UUID} time_lowtime_mid time_hi 字段构造<br>
* 所得到的时间戳以 100 毫微秒为单位 UTC通用协调时间 1582 10 15 日零时开始
*
* <p>
* 时间戳值仅在在基于时间的 UUID version 类型为 1中才有意义<br>
* 如果此 {@code UUID} 不是基于时间的 UUID则此方法抛出 UnsupportedOperationException
*
* @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 1 UUID
*/
public long timestamp() throws UnsupportedOperationException
{
checkTimeBase();
return (mostSigBits & 0x0FFFL) << 48
| ((mostSigBits >> 16) & 0x0FFFFL) << 32
| mostSigBits >>> 32;
}
/**
* 与此 UUID 相关联的时钟序列值
*
* <p>
* 14 位的时钟序列值根据此 UUID clock_seq 字段构造clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性
* <p>
* {@code clockSequence} 值仅在基于时间的 UUID version 类型为 1中才有意义 如果此 UUID 不是基于时间的 UUID则此方法抛出
* UnsupportedOperationException
*
* @return {@code UUID} 的时钟序列
*
* @throws UnsupportedOperationException 如果此 UUID version 不为 1
*/
public int clockSequence() throws UnsupportedOperationException
{
checkTimeBase();
return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
}
/**
* 与此 UUID 相关的节点值
*
* <p>
* 48 位的节点值根据此 UUID node 字段构造此字段旨在用于保存机器的 IEEE 802 地址该地址用于生成此 UUID 以保证空间唯一性
* <p>
* 节点值仅在基于时间的 UUID version 类型为 1中才有意义<br>
* 如果此 UUID 不是基于时间的 UUID则此方法抛出 UnsupportedOperationException
*
* @return {@code UUID} 的节点值
*
* @throws UnsupportedOperationException 如果此 UUID version 不为 1
*/
public long node() throws UnsupportedOperationException
{
checkTimeBase();
return leastSigBits & 0x0000FFFFFFFFFFFFL;
}
/**
* 返回此{@code UUID} 的字符串表现形式
*
* <p>
* UUID 的字符串表示形式由此 BNF 描述
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
* </blockquote>
*
* @return {@code UUID} 的字符串表现形式
* @see #toString(boolean)
*/
@Override
public String toString()
{
return toString(false);
}
/**
* 返回此{@code UUID} 的字符串表现形式
*
* <p>
* UUID 的字符串表示形式由此 BNF 描述
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
* </blockquote>
*
* @param isSimple 是否简单模式简单模式为不带'-'的UUID字符串
* @return {@code UUID} 的字符串表现形式
*/
public String toString(boolean isSimple)
{
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
// time_low
builder.append(digits(mostSigBits >> 32, 8));
if (false == isSimple)
{
builder.append('-');
}
// time_mid
builder.append(digits(mostSigBits >> 16, 4));
if (false == isSimple)
{
builder.append('-');
}
// time_high_and_version
builder.append(digits(mostSigBits, 4));
if (false == isSimple)
{
builder.append('-');
}
// variant_and_sequence
builder.append(digits(leastSigBits >> 48, 4));
if (false == isSimple)
{
builder.append('-');
}
// node
builder.append(digits(leastSigBits, 12));
return builder.toString();
}
/**
* 返回此 UUID 的哈希码
*
* @return UUID 的哈希码值
*/
@Override
public int hashCode()
{
long hilo = mostSigBits ^ leastSigBits;
return ((int) (hilo >> 32)) ^ (int) hilo;
}
/**
* 将此对象与指定对象比较
* <p>
* 当且仅当参数不为 {@code null}而是一个 UUID 对象具有与此 UUID 相同的 varriant包含相同的值每一位均相同结果才为 {@code true}
*
* @param obj 要与之比较的对象
*
* @return 如果对象相同则返回 {@code true}否则返回 {@code false}
*/
@Override
public boolean equals(Object obj)
{
if ((null == obj) || (obj.getClass() != UUID.class))
{
return false;
}
UUID id = (UUID) obj;
return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
}
// Comparison Operations
/**
* 将此 UUID 与指定的 UUID 比较
*
* <p>
* 如果两个 UUID 不同且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段则第一个 UUID 大于第二个 UUID
*
* @param val 与此 UUID 比较的 UUID
*
* @return 在此 UUID 小于等于或大于 val 分别返回 -10 1
*
*/
@Override
public int compareTo(UUID val)
{
// The ordering is intentionally set up so that the UUIDs
// can simply be numerically compared as two numbers
return (this.mostSigBits < val.mostSigBits ? -1 :
(this.mostSigBits > val.mostSigBits ? 1 :
(this.leastSigBits < val.leastSigBits ? -1 :
(this.leastSigBits > val.leastSigBits ? 1 :
0))));
}
// -------------------------------------------------------------------------------------------------------------------
// Private method start
/**
* 返回指定数字对应的hex值
*
* @param val
* @param digits
* @return
*/
private static String digits(long val, int digits)
{
long hi = 1L << (digits * 4);
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}
/**
* 检查是否为time-based版本UUID
*/
private void checkTimeBase()
{
if (version() != 1)
{
throw new UnsupportedOperationException("Not a time-based UUID");
}
}
/**
* 获取{@link SecureRandom}类提供加密的强随机数生成器 (RNG)
*
* @return {@link SecureRandom}
*/
public static SecureRandom getSecureRandom()
{
try
{
return SecureRandom.getInstance("SHA1PRNG");
}
catch (NoSuchAlgorithmException e)
{
throw new UtilException(e);
}
}
/**
* 获取随机数生成器对象<br>
* ThreadLocalRandom是JDK 7之后提供并发产生随机数能够解决多个线程发生的竞争争夺
*
* @return {@link ThreadLocalRandom}
*/
public static ThreadLocalRandom getRandom()
{
return ThreadLocalRandom.current();
}
}

View File

@ -3,10 +3,10 @@ package com.bonus.business.service.impl;
import com.alibaba.fastjson2.JSONArray;
import com.bonus.business.core.config.RedisService;
import com.bonus.business.mapper.RobotMapper;
import com.bonus.business.robot.util.Base64ImageMD5;
import com.bonus.business.robot.util.QxUtils;
import com.bonus.business.robot.util.XmlUtils;
import com.bonus.business.robot.util.XxmSendUtils;
import com.bonus.business.mongodb.service.FileService;
import com.bonus.business.mongodb.vo.FileExportVo;
import com.bonus.business.robot.util.*;
import org.bson.Document;
import com.bonus.business.robot.video.QxVideotape;
import com.bonus.business.robot.video.TVideoConfigUtil;
import com.bonus.business.service.IRobotService;
@ -23,6 +23,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -550,28 +552,35 @@ public class RobotServiceImpl implements IRobotService {
return AjaxResult.error("删除失败");
}
@Autowired
FileService fileService;
@Override
public AjaxResult addVideoFile(MultipartFile multipartFile,String puid) {
try{
String path= uploadFileService.uploadVideo(multipartFile);
String filePath = RuoYiConfig.getUploadPath();
String fileId=fileService.uploadFile(multipartFile);
FileExportVo data=fileService.getFileInfo(fileId);
String path=ImageResizer.transImageByJpg(filePath,data.getData(),data.getSuffix());
System.err.println(path);
String fileName=multipartFile.getOriginalFilename();
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1).toUpperCase();
String id="video_start_image";
mapper.addVideoFile(id,path,fileName,puid);
String token=redisService.get("qx","token");
if(StringUtil.isEmpty(token)){
token=QxVideotape.login(TVideoConfigUtil.getMaps(),TVideoConfigUtil.Q2HTTPURL);
redisService.set("qx:token",token,60*60);
}
//下发到机器人
String delXml= QxUtils.getAddVideo(XxmSendUtils.CONTROLLER,XxmSendUtils.ROBOT_DEL_VIDEO,id,null,null);
String delRes=QxVideotape.sendXmlPost(token,TVideoConfigUtil.Q2HTTPURL,puid,delXml);
//转成bast64
String bast64= Base64ImageMD5.convertToBase64(RuoYiConfig.getUploadPath()+path);
String xml= QxUtils.getAddVideo(XxmSendUtils.CONTROLLER,XxmSendUtils.ROBOT_ADD_VIDEO,id,suffix,bast64);
String res=QxVideotape.sendXmlPost(token,TVideoConfigUtil.Q2HTTPURL,puid,xml);
return AjaxResult.success(XmlUtils.getSuccess(res));
// String path= uploadFileService.uploadVideo(multipartFile);
// String fileName=multipartFile.getOriginalFilename();
// String suffix = fileName.substring(fileName.lastIndexOf(".") + 1).toUpperCase();
// String id="video_start_image";
// mapper.addVideoFile(id,path,fileName,puid);
// String token=redisService.get("qx","token");
// if(StringUtil.isEmpty(token)){
// token=QxVideotape.login(TVideoConfigUtil.getMaps(),TVideoConfigUtil.Q2HTTPURL);
// redisService.set("qx:token",token,60*60);
// }
// //下发到机器人
// String delXml= QxUtils.getAddVideo(XxmSendUtils.CONTROLLER,XxmSendUtils.ROBOT_DEL_VIDEO,id,null,null);
// String delRes=QxVideotape.sendXmlPost(token,TVideoConfigUtil.Q2HTTPURL,puid,delXml);
// //转成bast64
// String bast64= Base64ImageMD5.convertToBase64(RuoYiConfig.getUploadPath()+path);
// String xml= QxUtils.getAddVideo(XxmSendUtils.CONTROLLER,XxmSendUtils.ROBOT_ADD_VIDEO,id,suffix,bast64);
// String res=QxVideotape.sendXmlPost(token,TVideoConfigUtil.Q2HTTPURL,puid,xml);
// return AjaxResult.success(XmlUtils.getSuccess(res));
}catch (Exception e){
log.error(e.toString(),e);
}

View File

@ -72,4 +72,11 @@ spring:
merge-sql: true
wall:
config:
multi-statement-allow: true
multi-statement-allow: true
data:
mongodb:
host: 127.0.0.1
port: 27017
database: robot
username: robot
password: adminPassword

View File

@ -16,7 +16,7 @@ ruoyi:
# 开发环境配置
server:
# 服务器的HTTP端口默认为8080
port: 21999
port: 58080
servlet:
# 应用的访问路径
context-path: /