feat(image): 添加图片清理功能- 新增 FileStorageService 用于文件上传、下载和删除操作- 实现 ImageCleanupService 清理冗余图片
- 添加 ImageCleanupController 提供手动清理图片的 API - 创建 ImageCleanupScheduler定时清理冗余图片 - 更新相关 Mapper 接口,增加必要的查询和删除方法
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
package com.test.bijihoudaun.controller;
|
||||
|
||||
import com.test.bijihoudaun.service.ImageCleanupService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 图片清理控制器
|
||||
* 提供手动触发清理冗余图片的API端点
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/admin")
|
||||
public class ImageCleanupController {
|
||||
|
||||
@Autowired
|
||||
private ImageCleanupService imageCleanupService;
|
||||
|
||||
/**
|
||||
* 手动触发清理冗余图片
|
||||
* @return 清理结果
|
||||
*/
|
||||
@PostMapping("/cleanup-images")
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
public ResponseEntity<?> cleanupImages() {
|
||||
int deletedCount = imageCleanupService.cleanupRedundantImages();
|
||||
return ResponseEntity.ok().body("成功清理 " + deletedCount + " 个冗余图片");
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package com.test.bijihoudaun.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.test.bijihoudaun.entity.Image;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ImageMapper extends BaseMapper<Image> {
|
||||
@@ -11,4 +13,11 @@ public interface ImageMapper extends BaseMapper<Image> {
|
||||
|
||||
// 自定义方法:根据Markdown文件ID获取关联图片
|
||||
// List<Image> findByMarkdownId(Integer markdownId);
|
||||
|
||||
/**
|
||||
* 获取所有图片记录
|
||||
* @return 所有图片列表
|
||||
*/
|
||||
@Select("SELECT * FROM image")
|
||||
List<Image> findAll();
|
||||
}
|
||||
@@ -3,8 +3,17 @@ package com.test.bijihoudaun.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.test.bijihoudaun.entity.ImageName;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
|
||||
@Mapper
|
||||
public interface ImageNameMapper extends BaseMapper<ImageName> {
|
||||
// 可以在这里添加自定义方法
|
||||
|
||||
/**
|
||||
* 根据文件名删除记录
|
||||
* @param fileName 文件名
|
||||
* @return 删除的记录数
|
||||
*/
|
||||
@Delete("DELETE FROM image_name WHERE file_name = #{fileName}")
|
||||
int deleteByFileName(String fileName);
|
||||
}
|
||||
|
||||
@@ -43,4 +43,11 @@ public interface MarkdownFileMapper extends BaseMapper<MarkdownFile> {
|
||||
void restoreById(@Param("id") Long id);
|
||||
@Delete("DELETE FROM markdown_file WHERE is_deleted = 1")
|
||||
void physicalDeleteByIsDeleted();
|
||||
|
||||
/**
|
||||
* 获取所有笔记ID
|
||||
* @return 所有笔记ID列表
|
||||
*/
|
||||
@Select("SELECT id FROM markdown_file WHERE is_deleted = 0")
|
||||
List<Integer> findAllIds();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.test.bijihoudaun.scheduler;
|
||||
|
||||
import com.test.bijihoudaun.service.ImageCleanupService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 图片清理定时任务
|
||||
* 定期自动清理冗余图片
|
||||
*/
|
||||
@Component
|
||||
public class ImageCleanupScheduler {
|
||||
|
||||
@Autowired
|
||||
private ImageCleanupService imageCleanupService;
|
||||
|
||||
/**
|
||||
* 定时清理任务
|
||||
* 每天凌晨3点执行一次清理任务
|
||||
*/
|
||||
@Scheduled(cron = "0 0 3 * * ?")
|
||||
public void scheduledCleanup() {
|
||||
int deletedCount = imageCleanupService.cleanupRedundantImages();
|
||||
System.out.println("定时清理任务完成,清理了 " + deletedCount + " 个冗余图片");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.test.bijihoudaun.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* 文件存储服务
|
||||
* 用于处理文件上传、下载和删除等操作
|
||||
*/
|
||||
@Service
|
||||
public class FileStorageService {
|
||||
|
||||
@Value("${file.upload-dir}")
|
||||
private String uploadDir;
|
||||
|
||||
/**
|
||||
* 加载文件作为File对象
|
||||
* @param filename 文件名
|
||||
* @return 文件对象
|
||||
*/
|
||||
public java.io.File loadAsFile(String filename) {
|
||||
return new java.io.File(uploadDir + java.io.File.separator + filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* @param filename 文件名
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
public boolean deleteFile(String filename) {
|
||||
try {
|
||||
Path filePath = Paths.get(uploadDir, filename);
|
||||
return Files.deleteIfExists(filePath);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Failed to delete file: " + filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.test.bijihoudaun.service;
|
||||
|
||||
import com.test.bijihoudaun.util.MarkdownImageExtractor;
|
||||
import com.test.bijihoudaun.mapper.ImageMapper;
|
||||
import com.test.bijihoudaun.mapper.MarkdownFileMapper;
|
||||
import com.test.bijihoudaun.mapper.ImageNameMapper;
|
||||
import com.test.bijihoudaun.entity.Image;
|
||||
import com.test.bijihoudaun.entity.MarkdownFile;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* 图片清理服务类
|
||||
* 用于清理不再被笔记引用的冗余图片
|
||||
*/
|
||||
@Service
|
||||
public class ImageCleanupService {
|
||||
|
||||
@Autowired
|
||||
private ImageMapper imageMapper;
|
||||
|
||||
@Autowired
|
||||
private MarkdownFileMapper markdownFileMapper;
|
||||
|
||||
@Autowired
|
||||
private ImageNameMapper imageNameMapper;
|
||||
|
||||
@Autowired
|
||||
private FileStorageService fileStorageService;
|
||||
|
||||
/**
|
||||
* 清理冗余图片
|
||||
* @return 清理的图片数量
|
||||
*/
|
||||
@Transactional
|
||||
public int cleanupRedundantImages() {
|
||||
// 获取所有笔记ID
|
||||
List<Integer> allMarkdownIds = markdownFileMapper.findAllIds();
|
||||
|
||||
// 用于存储所有被引用的图片文件名
|
||||
Set<String> referencedImageNames = new HashSet<>();
|
||||
|
||||
// 遍历所有笔记,收集被引用的图片
|
||||
for (Integer markdownId : allMarkdownIds) {
|
||||
MarkdownFile markdownFile = markdownFileMapper.selectById(markdownId);
|
||||
String content = (markdownFile != null) ? markdownFile.getContent() : "";
|
||||
|
||||
List<String> imageNames = MarkdownImageExtractor.extractImageFilenames(content);
|
||||
referencedImageNames.addAll(imageNames);
|
||||
}
|
||||
|
||||
// 获取所有图片记录
|
||||
List<Image> allImages = imageMapper.findAll();
|
||||
|
||||
// 记录被删除的图片数量
|
||||
int deletedCount = 0;
|
||||
|
||||
// 遍历所有图片,删除未被引用的
|
||||
for (Image image : allImages) {
|
||||
if (!referencedImageNames.contains(image.getStoredName())) {
|
||||
// 删除物理文件
|
||||
fileStorageService.deleteFile(image.getStoredName());
|
||||
|
||||
// 删除数据库记录
|
||||
imageMapper.deleteById(image.getId());
|
||||
|
||||
// 如果存在image_name表中的记录,也一并删除
|
||||
imageNameMapper.deleteByFileName(image.getStoredName());
|
||||
|
||||
deletedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return deletedCount;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user