Browse Source

添加检测本地服务版本从远程获取更新功能

zhaojinyu 2 weeks ago
parent
commit
475dccfd41

+ 4 - 0
base-modules/service-file/pom.xml

@@ -88,6 +88,10 @@
             <artifactId>mysql-connector-java</artifactId>
             <scope>runtime</scope>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
 
     </dependencies>
 

+ 110 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/controller/FileUpdateController.java

@@ -0,0 +1,110 @@
+package com.ruoyi.file.controller;
+
+import com.ruoyi.file.model.FileUpdateInfo;
+import com.ruoyi.file.repository.FileUpdateInfoRepository;
+import com.ruoyi.file.service.FileUpdateRequest;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.core.bean.CommonPage;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import com.ruoyi.file.service.FileUpdateService;
+
+import java.util.List;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/update")
+public class FileUpdateController {
+
+    @Autowired
+    private FileUpdateService fileUpdateService;
+
+    @Autowired
+    private FileUpdateInfoRepository fileUpdateInfoRepository;
+
+    @PostMapping("/add")
+    public ApiResult<String> addFileToDatabase(@RequestBody FileUpdateRequest request) {
+        try {
+            fileUpdateService.addFileToDatabase(request);
+            return ApiResult.success("文件信息录入成功");
+        } catch (Exception e) {
+            return ApiResult.error("文件信息录入失败: " + e.getMessage());
+        }
+    }
+
+    // 检查文件是否需要更新
+    @PostMapping("/checkById")
+    public ApiResult<String> checkFileUpdate(@RequestParam Long id) {
+        try {
+            boolean isUpdateRequired = fileUpdateService.checkFileUpdate(id);
+            return ApiResult.success(isUpdateRequired ? "需要更新" : "不需要更新");
+        } catch (Exception e) {
+            return ApiResult.error("检查文件更新失败: " + e.getMessage());
+        }
+    }
+
+    // 执行文件更新
+    @PostMapping("/reloadById")
+    public ApiResult<String> performFileUpdate(@RequestParam Long id) {
+        try {
+            fileUpdateService.performFileUpdate(id);
+            return ApiResult.success("文件更新成功");
+        } catch (Exception e) {
+            return ApiResult.error("文件更新失败: " + e.getMessage());
+        }
+    }
+
+    // 新增查询接口
+    @GetMapping("/query")
+    public ApiResult<CommonPage<FileUpdateInfo>> queryFiles(
+            @RequestParam(required = false) String fileName,
+            @RequestParam(required = false, defaultValue = "1") int current,
+            @RequestParam(required = false, defaultValue = "10") int size) {
+        try {
+            // 创建 Pageable 对象
+            Pageable pageable = PageRequest.of(current - 1, size);
+
+            Page<FileUpdateInfo> page;
+            if (fileName == null || fileName.trim().isEmpty()) {
+                // 查询所有记录
+                page = fileUpdateInfoRepository.findAll(pageable);
+            } else {
+                // 按文件名模糊查询
+                page = fileUpdateInfoRepository.findByFileNameContaining(fileName, pageable);
+            }
+
+            // 将 Page 转换为 CommonPage
+            CommonPage<FileUpdateInfo> commonPage = new CommonPage<>(
+                    page.getContent(), // 数据
+                    page.getTotalElements(), // 总记录数
+                    size, // 每页大小
+                    current // 当前页码
+            );
+            return ApiResult.success(commonPage);
+        } catch (Exception e) {
+            return ApiResult.error("查询文件信息失败: " + e.getMessage());
+        }
+    }
+
+    // 新增删除接口
+    @DeleteMapping("/deleteById")
+    @ApiOperation(value = "删除文件信息", notes = "根据文件 ID 删除指定文件信息")
+    public ApiResult<String> deleteFileById(@RequestParam Long id) {
+        try {
+            Optional<FileUpdateInfo> fileUpdateInfo = fileUpdateInfoRepository.findById(id);
+            if (fileUpdateInfo.isPresent()) {
+                fileUpdateInfoRepository.deleteById(id);
+                return ApiResult.success("文件信息删除成功");
+            } else {
+                return ApiResult.error("文件信息未找到");
+            }
+        } catch (Exception e) {
+            return ApiResult.error("删除文件信息失败: " + e.getMessage());
+        }
+    }
+}

+ 87 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/model/FileUpdateInfo.java

@@ -0,0 +1,87 @@
+package com.ruoyi.file.model;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "file_update_info")
+public class FileUpdateInfo {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "file_name", nullable = false) // 新增字段
+    private String fileName;
+
+    @Column(name = "file_path", nullable = false)
+    private String filePath;
+
+    @Column(name = "file_md5", nullable = false)
+    private String fileMd5;
+
+    @Column(name = "remote_md5", nullable = true)
+    private String remoteMd5;
+
+    @Column(name = "update_time", nullable = false)
+    private java.util.Date updateTime;
+
+    @Column(name = "update_status", nullable = false)
+    private String updateStatus;
+
+    // Getters and Setters
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getFileName() { // 新增 Getter
+        return fileName;
+    }
+
+    public void setFileName(String fileName) { // 新增 Setter
+        this.fileName = fileName;
+    }
+
+    public String getFilePath() {
+        return filePath;
+    }
+
+    public void setFilePath(String filePath) {
+        this.filePath = filePath;
+    }
+
+    public String getFileMd5() {
+        return fileMd5;
+    }
+
+    public void setFileMd5(String fileMd5) {
+        this.fileMd5 = fileMd5;
+    }
+
+    public String getRemoteMd5() {
+        return remoteMd5;
+    }
+
+    public void setRemoteMd5(String remoteMd5) {
+        this.remoteMd5 = remoteMd5;
+    }
+
+    public java.util.Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(java.util.Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getUpdateStatus() {
+        return updateStatus;
+    }
+
+    public void setUpdateStatus(String updateStatus) {
+        this.updateStatus = updateStatus;
+    }
+}

+ 13 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/repository/FileUpdateInfoRepository.java

@@ -0,0 +1,13 @@
+package com.ruoyi.file.repository;
+
+import com.ruoyi.file.model.FileUpdateInfo;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+
+public interface FileUpdateInfoRepository extends JpaRepository<FileUpdateInfo, Long> {
+
+    Page<FileUpdateInfo> findByFileNameContaining(String fileName, Pageable pageable);
+}

+ 9 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/service/FileUpdateRequest.java

@@ -0,0 +1,9 @@
+package com.ruoyi.file.service;
+
+import lombok.Data;
+
+@Data
+public class FileUpdateRequest {
+    private String fileName;
+    private String filePath;
+}

+ 140 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/service/FileUpdateService.java

@@ -0,0 +1,140 @@
+package com.ruoyi.file.service;
+
+import com.ruoyi.file.model.FileUpdateInfo;
+import com.ruoyi.file.repository.FileUpdateInfoRepository;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+@Service
+public class FileUpdateService {
+
+    @Autowired
+    private FileUpdateInfoRepository fileUpdateInfoRepository;
+
+    public void addFileToDatabase(FileUpdateRequest request) throws Exception {
+        String fileName = request.getFileName();
+        String filePath = request.getFilePath();
+
+        File file = new File(filePath);
+        if (!file.exists()) {
+            throw new FileNotFoundException("文件不存在:" + filePath);
+        }
+
+        String fileMd5 = DigestUtils.md5Hex(new FileInputStream(file));
+        FileUpdateInfo fileUpdateInfo = new FileUpdateInfo();
+        fileUpdateInfo.setFileName(fileName);
+        fileUpdateInfo.setFilePath(filePath);
+        fileUpdateInfo.setFileMd5(fileMd5);
+        fileUpdateInfo.setUpdateTime(new Date());
+        fileUpdateInfo.setUpdateStatus("待检查文件版本");
+        fileUpdateInfoRepository.save(fileUpdateInfo);
+    }
+
+    // 检查文件是否需要更新
+    public boolean checkFileUpdate(Long id) throws Exception {
+        FileUpdateInfo fileUpdateInfo = fileUpdateInfoRepository.findById(id).orElse(null);
+        if (fileUpdateInfo == null) {
+            throw new FileNotFoundException("文件信息未找到:id=" + id);
+        }
+
+        String localFilePath = fileUpdateInfo.getFilePath();
+        String localFileMd5 = fileUpdateInfo.getFileMd5();
+        String fileName = fileUpdateInfo.getFileName(); // 获取文件名
+        String remoteFileMd5 = getRemoteFileMd5(fileName); // 获取远程文件的 MD5 值
+
+        boolean isUpdateRequired = !localFileMd5.equals(remoteFileMd5);
+        fileUpdateInfo.setRemoteMd5(remoteFileMd5); // 更新远程文件的 MD5 值
+        fileUpdateInfo.setUpdateTime(new Date());
+        fileUpdateInfo.setUpdateStatus(isUpdateRequired ? "待更新" : "无需更新");
+        fileUpdateInfoRepository.save(fileUpdateInfo);
+
+        return isUpdateRequired;
+    }
+
+    // 执行文件更新
+    public void performFileUpdate(Long id) throws Exception {
+        FileUpdateInfo fileUpdateInfo = fileUpdateInfoRepository.findById(id).orElse(null);
+        if (fileUpdateInfo == null) {
+            throw new FileNotFoundException("文件信息未找到:id=" + id);
+        }
+
+        String localFilePath = fileUpdateInfo.getFilePath();
+        String fileName = fileUpdateInfo.getFileName(); // 获取文件名
+        String remoteUrl = "https://file.usky.cn/uskycloud/" + fileName; // 替换为实际的远程文件 URL
+
+        try {
+            // 检查并创建备份目录
+            String backupDirPath = localFilePath + "-backup";
+            File backupDir = new File(backupDirPath);
+            if (!backupDir.exists()) {
+                boolean created = backupDir.mkdirs();
+                if (!created) {
+                    throw new IOException("无法创建备份目录: " + backupDirPath);
+                }
+            }
+
+            // 为旧文件添加时间戳并移动到备份目录
+            File originalFile = new File(localFilePath);
+            if (originalFile.exists()) {
+                String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
+                String backupFilePath = backupDirPath + File.separator + fileName + "." + timestamp;
+                Files.move(originalFile.toPath(), Paths.get(backupFilePath), StandardCopyOption.REPLACE_EXISTING);
+                System.out.println("旧文件已备份到: " + backupFilePath);
+            }
+
+            // 下载远程文件
+            downloadFileFromRemote(remoteUrl, localFilePath);
+
+            // 更新数据库中的文件信息
+            String newFileMd5 = DigestUtils.md5Hex(new FileInputStream(localFilePath));
+            fileUpdateInfo.setFileMd5(newFileMd5);
+            fileUpdateInfo.setUpdateTime(new Date());
+            fileUpdateInfo.setUpdateStatus("已更新");
+            fileUpdateInfoRepository.save(fileUpdateInfo);
+        } catch (FileNotFoundException e) {
+            throw new Exception("文件未找到: " + localFilePath + ",原因: " + e.getMessage(), e);
+        } catch (IOException e) {
+            throw new Exception("文件写入失败: " + localFilePath + ",原因: " + e.getMessage(), e);
+        } catch (Exception e) {
+            throw new Exception("文件更新失败: " + localFilePath + ",原因: " + e.getMessage(), e);
+        }
+    }
+
+    private void downloadFileFromRemote(String remoteUrl, String localFilePath) throws Exception {
+        URL url = new URL(remoteUrl);
+        Path path = Paths.get(localFilePath);
+        try {
+            Files.copy(url.openStream(), path, StandardCopyOption.REPLACE_EXISTING);
+            System.out.println("文件下载成功: " + localFilePath);
+        } catch (IOException e) {
+            System.err.println("文件下载失败: " + localFilePath + ",原因: " + e.getMessage());
+            throw new Exception("文件下载失败: " + localFilePath, e);
+        }
+    }
+
+
+    private String getRemoteFileMd5(String fileName) throws Exception {
+        String remoteUrl = "https://file.usky.cn/uskycloud/" + fileName;
+        System.out.println("远程文件 URL: " + remoteUrl);
+        URL url = new URL(remoteUrl);
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        connection.setRequestProperty("Cache-Control", "no-cache");
+        try (InputStream in = connection.getInputStream()) {
+            return DigestUtils.md5Hex(in);
+        }
+    }
+}