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; 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.entity.dao.Image;
import com.unisinsight.project.exception.BaseErrorCode; import com.unisinsight.project.exception.BaseErrorCode;
import com.unisinsight.project.exception.Result; import com.unisinsight.project.exception.Result;
@ -10,8 +13,11 @@ import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Value; 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.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -21,10 +27,8 @@ import java.io.OutputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Comparator; import java.util.*;
import java.util.HashMap; import java.util.concurrent.CompletableFuture;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
@ -44,6 +48,14 @@ public class FileChunkController {
@Value("${file.upload.dir:${user.home}/uploads}") @Value("${file.upload.dir:${user.home}/uploads}")
private String uploadDir; private String uploadDir;
// 请求bt配置
@Value("${file.upload.bt-url}")
private String btUrl;
@Resource
private RestTemplate restTemplate;
// 存储每个文件的分片信息 // 存储每个文件的分片信息
private final Map<String, FileUploadInfo> fileUploadMap = new ConcurrentHashMap<>(); private final Map<String, FileUploadInfo> fileUploadMap = new ConcurrentHashMap<>();
@ -95,13 +107,20 @@ public class FileChunkController {
log.info("分片文件md5校验失败,chunkMd5:{},md5:{}", chunkMd5, md5); log.info("分片文件md5校验失败,chunkMd5:{},md5:{}", chunkMd5, md5);
throw new RuntimeException("分片文件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); Path fileTempDir = Paths.get(tempDir, fileId);
if (!Files.exists(fileTempDir)) { if (!Files.exists(fileTempDir)) {
Files.createDirectories(fileTempDir); Files.createDirectories(fileTempDir);
} }
log.info("创建临时目录: {}", fileTempDir);
log.info("上传分片文件: {}", fileName);
// 保存分片文件 // 保存分片文件
String chunkFileName = String.format("%05d.part", chunkNumber); String chunkFileName = String.format("%05d.part", chunkNumber);
log.info("保存分片文件: {}", chunkFileName); log.info("保存分片文件: {}", chunkFileName);
@ -120,9 +139,8 @@ public class FileChunkController {
if (!Files.exists(finalDir)) { if (!Files.exists(finalDir)) {
Files.createDirectories(finalDir); Files.createDirectories(finalDir);
} }
log.info("合并文件: {}", finalDir);
Path finalFilePath = finalDir.resolve(fileName); Path finalFilePath = finalDir.resolve(fileName);
log.info("合并所有分片文件: {}", finalFilePath.getFileName()); log.info("合并所有分片文件: {}", finalFilePath);
mergeChunks(fileId, finalFilePath, totalChunks); mergeChunks(fileId, finalFilePath, totalChunks);
// 清理临时文件 // 清理临时文件
@ -134,11 +152,41 @@ public class FileChunkController {
Image image = new Image(); Image image = new Image();
image.setImageName(fileName); image.setImageName(fileName);
image.setStoragePath(uploadDir); image.setStoragePath(String.valueOf(finalFilePath));
image.setImageStatus(1); image.setImageStatus(1);
int insert = imageMapper.insert(image); int insert = imageMapper.insert(image);
log.info("镜像新增insert:{}", insert); log.info("镜像新增insert:{}", insert);
if (insert == 1) { 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("status", "completed");
response.put("message", "文件上传并合并完成"); response.put("message", "文件上传并合并完成");
response.put("filePath", finalFilePath.toString()); response.put("filePath", finalFilePath.toString());
@ -159,8 +207,8 @@ public class FileChunkController {
} catch (Exception e) { } catch (Exception e) {
response.put("success", false); response.put("success", false);
response.put("status", "error"); response.put("status", "error");
response.put("message", "上传失败: " + e.getMessage()); response.put("message", "上传失败");
log.info("上次失败清理临时文件: {}", fileId); log.info("上次失败清理临时文件: {},error:{}", fileId, e.getMessage(), e);
try { try {
cleanupTempFiles(fileId); cleanupTempFiles(fileId);
cleanUploadFile(fileName); cleanUploadFile(fileName);
@ -179,6 +227,8 @@ public class FileChunkController {
} }
log.info("取消上传,清理临时文件: {}", fileId); log.info("取消上传,清理临时文件: {}", fileId);
try { try {
// 从上传映射中移除
fileUploadMap.remove(fileId);
cleanupTempFiles(fileId); cleanupTempFiles(fileId);
} catch (IOException ex) { } catch (IOException ex) {
log.error("清理临时文件失败,fileId:{}, {}", fileId, ex.getMessage(), 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 com.unisinsight.project.util.BtTorrentUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.io.*; import org.springframework.web.bind.annotation.RestController;
@RestController("test") @RestController("test")
@Slf4j @Slf4j
public class TestController { public class TestController {
@GetMapping("/start") @GetMapping("/start")
public String start(@RequestParam("sourceFile") String sourceFile, public boolean start(@RequestParam("sourceFile") String sourceFile,
@RequestParam("torrentFile") String torrentFile) { @RequestParam("torrentFile") String torrentFile) {
System.out.println("开始做种..."); System.out.println("开始做种...");
boolean seedResult = BtTorrentUtils.createAndSeed(sourceFile, torrentFile); boolean seedResult = BtTorrentUtils.createAndSeed(sourceFile, torrentFile);
System.out.println("做种结果: " + (seedResult ? "成功" : "失败")); System.out.println("做种结果: " + (seedResult ? "成功" : "失败"));
return "success"; return seedResult;
} }
@GetMapping("/stop") @GetMapping("/stop")

View File

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

View File

@ -154,8 +154,10 @@ public class DeviceUserMappingServiceImpl extends ServiceImpl<DeviceUserMappingM
if (CollectionUtil.isEmpty(users)) { if (CollectionUtil.isEmpty(users)) {
return Result.errorResultMessage(BaseErrorCode.PARAMS_CHK_ERROR, "用户不存在,请重试"); 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())) { if (!users.get(0).getPassword().equals(deviceUserReq.getPassword())) {
return Result.errorResultMessage(BaseErrorCode.PARAMS_CHK_ERROR, "密码错误,请重新输入"); 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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; 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.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.IOException; import java.io.IOException;
@ -39,6 +44,14 @@ public class ImageServiceImpl extends ServiceImpl<ImageMapper, Image>
@Resource @Resource
private ImageMapper imageMapper; private ImageMapper imageMapper;
// 请求bt配置
@Value("${file.upload.bt-url}")
private String btUrl;
@Resource
private RestTemplate restTemplate;
@Override @Override
public Result<?> selectPage(ImageReq imageReq) { public Result<?> selectPage(ImageReq imageReq) {
Page<Image> page = new Page<>(imageReq.getPageNum(), imageReq.getPageSize()); 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()); Image image = imageMapper.selectById(deleteIdReq.getId());
if (ObjectUtils.isNotEmpty(image)) { if (ObjectUtils.isNotEmpty(image)) {
try { 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)) { if (Files.exists(filePath)) {
// 删除文件 // 删除文件
Files.delete(filePath); Files.delete(filePath);