feat(后端): 联调修改2

master
rdpnr_puzhi 2025-08-12 19:14:17 +08:00
parent 6cf65aeb83
commit cccfb7bd86
6 changed files with 121 additions and 20 deletions

View File

@ -0,0 +1,20 @@
package com.unisinsight.project.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @description:
* @author: rdpnr_puzhi
* @create: 2025/08/12
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

View File

@ -1,5 +1,8 @@
package com.unisinsight.project.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.unisinsight.project.entity.dao.Image;
import com.unisinsight.project.exception.BaseErrorCode;
import com.unisinsight.project.exception.Result;
@ -10,8 +13,11 @@ import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
@ -21,10 +27,8 @@ import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
/**
@ -44,6 +48,14 @@ public class FileChunkController {
@Value("${file.upload.dir:${user.home}/uploads}")
private String uploadDir;
// 请求bt配置
@Value("${file.upload.bt-url}")
private String btUrl;
@Resource
private RestTemplate restTemplate;
// 存储每个文件的分片信息
private final Map<String, FileUploadInfo> fileUploadMap = new ConcurrentHashMap<>();
@ -95,13 +107,20 @@ public class FileChunkController {
log.info("分片文件md5校验失败,chunkMd5:{},md5:{}", chunkMd5, md5);
throw new RuntimeException("分片文件md5校验失败");
}
QueryWrapper<Image> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(Image::getImageName, fileName);
List<Image> imageList = imageMapper.selectList(wrapper);
if (CollectionUtil.isNotEmpty(imageList)) {
response.put("success", false);
response.put("status", "error");
response.put("message", "当前文件已经上传");
return ResponseEntity.status(200).body(response);
}
// 创建临时目录
Path fileTempDir = Paths.get(tempDir, fileId);
if (!Files.exists(fileTempDir)) {
Files.createDirectories(fileTempDir);
}
log.info("创建临时目录: {}", fileTempDir);
log.info("上传分片文件: {}", fileName);
// 保存分片文件
String chunkFileName = String.format("%05d.part", chunkNumber);
log.info("保存分片文件: {}", chunkFileName);
@ -120,9 +139,8 @@ public class FileChunkController {
if (!Files.exists(finalDir)) {
Files.createDirectories(finalDir);
}
log.info("合并文件: {}", finalDir);
Path finalFilePath = finalDir.resolve(fileName);
log.info("合并所有分片文件: {}", finalFilePath.getFileName());
log.info("合并所有分片文件: {}", finalFilePath);
mergeChunks(fileId, finalFilePath, totalChunks);
// 清理临时文件
@ -134,11 +152,41 @@ public class FileChunkController {
Image image = new Image();
image.setImageName(fileName);
image.setStoragePath(uploadDir);
image.setStoragePath(String.valueOf(finalFilePath));
image.setImageStatus(1);
int insert = imageMapper.insert(image);
log.info("镜像新增insert:{}", insert);
if (insert == 1) {
// 异步执行创建和做种操作
CompletableFuture.runAsync(() -> {
try {
String url = btUrl + "/test/start?sourceFile=%s&torrentFile=%s";
url = String.format(url, finalFilePath, finalFilePath + ".torrent");
log.info("请求bt创建接口参数: {}", url);
ResponseEntity<Boolean> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, Boolean.class);
log.info("请求bt创建接口返回: {}", JSONUtil.toJsonStr(responseEntity));
HttpStatus statusCode = responseEntity.getStatusCode();
if (statusCode != HttpStatus.OK) {
boolean result = Boolean.TRUE.equals(responseEntity.getBody());
if (result) {
log.info("请求bt创建接口成功");
QueryWrapper<Image> imageQueryWrapper = new QueryWrapper<>();
imageQueryWrapper.lambda().eq(Image::getImageName, fileName);
Image imageBt = imageMapper.selectOne(imageQueryWrapper);
if (ObjectUtils.isNotEmpty(imageBt)) {
imageBt.setBtPath(finalFilePath + ".torrent");
int update = imageMapper.updateById(imageBt);
log.info("镜像bt更新insert:{}", update);
} else {
log.info("镜像bt更新查询失败:{}", fileName);
}
}
}
} catch (Exception e) {
log.error("请求bt创建接口失败: {}", e.getMessage(), e);
}
});
response.put("status", "completed");
response.put("message", "文件上传并合并完成");
response.put("filePath", finalFilePath.toString());
@ -159,8 +207,8 @@ public class FileChunkController {
} catch (Exception e) {
response.put("success", false);
response.put("status", "error");
response.put("message", "上传失败: " + e.getMessage());
log.info("上次失败清理临时文件: {}", fileId);
response.put("message", "上传失败");
log.info("上次失败清理临时文件: {},error:{}", fileId, e.getMessage(), e);
try {
cleanupTempFiles(fileId);
cleanUploadFile(fileName);
@ -179,6 +227,8 @@ public class FileChunkController {
}
log.info("取消上传,清理临时文件: {}", fileId);
try {
// 从上传映射中移除
fileUploadMap.remove(fileId);
cleanupTempFiles(fileId);
} catch (IOException ex) {
log.error("清理临时文件失败,fileId:{}, {}", fileId, ex.getMessage(), ex);

View File

@ -2,21 +2,21 @@ package com.unisinsight.project.controller;
import com.unisinsight.project.util.BtTorrentUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.io.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController("test")
@Slf4j
public class TestController {
@GetMapping("/start")
public String start(@RequestParam("sourceFile") String sourceFile,
public boolean start(@RequestParam("sourceFile") String sourceFile,
@RequestParam("torrentFile") String torrentFile) {
System.out.println("开始做种...");
boolean seedResult = BtTorrentUtils.createAndSeed(sourceFile, torrentFile);
System.out.println("做种结果: " + (seedResult ? "成功" : "失败"));
return "success";
return seedResult;
}
@GetMapping("/stop")

View File

@ -32,7 +32,7 @@ public class Image implements Serializable {
private Integer imageType;
/**
* : 1-2-
* : 1-2-,3-
*/
@TableField(value = "image_status")
private Integer imageStatus;

View File

@ -154,8 +154,10 @@ public class DeviceUserMappingServiceImpl extends ServiceImpl<DeviceUserMappingM
if (CollectionUtil.isEmpty(users)) {
return Result.errorResultMessage(BaseErrorCode.PARAMS_CHK_ERROR, "用户不存在,请重试");
}
users = users.stream().distinct().collect(Collectors.toList());
users = users.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
if (CollectionUtil.isEmpty(users)) {
return Result.errorResultMessage(BaseErrorCode.PARAMS_CHK_ERROR, "用户不存在,请重试");
}
if (!users.get(0).getPassword().equals(deviceUserReq.getPassword())) {
return Result.errorResultMessage(BaseErrorCode.PARAMS_CHK_ERROR, "密码错误,请重新输入");
}

View File

@ -18,7 +18,12 @@ import com.unisinsight.project.service.ImageService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.io.IOException;
@ -39,6 +44,14 @@ public class ImageServiceImpl extends ServiceImpl<ImageMapper, Image>
@Resource
private ImageMapper imageMapper;
// 请求bt配置
@Value("${file.upload.bt-url}")
private String btUrl;
@Resource
private RestTemplate restTemplate;
@Override
public Result<?> selectPage(ImageReq imageReq) {
Page<Image> page = new Page<>(imageReq.getPageNum(), imageReq.getPageSize());
@ -67,7 +80,23 @@ public class ImageServiceImpl extends ServiceImpl<ImageMapper, Image>
Image image = imageMapper.selectById(deleteIdReq.getId());
if (ObjectUtils.isNotEmpty(image)) {
try {
Path filePath = Paths.get(image.getStoragePath(), image.getImageName());
try {
String url = btUrl + "/test/stop?sourceFile=%s";
url = String.format(url, image.getStoragePath());
log.info("请求bt停止接口参数: {}", url);
ResponseEntity<Boolean> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, Boolean.class);
log.info("请求bt停止接口返回: {}", JSONUtil.toJsonStr(responseEntity));
HttpStatus statusCode = responseEntity.getStatusCode();
if (statusCode != HttpStatus.OK) {
boolean result = responseEntity.getBody();
if (result) {
log.info("请求bt停止接口成功");
}
}
} catch (Exception e) {
log.error("请求bt停止接口失败: {}", e.getMessage(), e);
}
Path filePath = Paths.get(image.getStoragePath());
if (Files.exists(filePath)) {
// 删除文件
Files.delete(filePath);