diff --git a/minio-plus-application/minio-plus-application-schedule/pom.xml b/minio-plus-application/minio-plus-application-schedule/pom.xml
new file mode 100644
index 0000000..2f778de
--- /dev/null
+++ b/minio-plus-application/minio-plus-application-schedule/pom.xml
@@ -0,0 +1,40 @@
+
+
+
+ minio-plus-application
+ me.liuxp
+ ${revision}
+
+ 4.0.0
+
+ minio-plus-application-schedule
+ jar
+
+
+
+ me.liuxp
+ minio-plus-core-spring-boot-starter
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ mysql
+ mysql-connector-java
+
+
+ com.squareup.okhttp3
+ okhttp
+ 4.11.0
+
+
+
+
\ No newline at end of file
diff --git a/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/ScheduleApplication.java b/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/ScheduleApplication.java
new file mode 100644
index 0000000..bb894cf
--- /dev/null
+++ b/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/ScheduleApplication.java
@@ -0,0 +1,20 @@
+package org.liuxp.minioplus.application.schedule;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * 定时任务启动类
+ * @author contact@liuxp.me
+ * @since 2024/06/17
+ */
+@SpringBootApplication
+@EnableScheduling
+public class ScheduleApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ScheduleApplication.class, args);
+ }
+
+}
\ No newline at end of file
diff --git a/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/dao/MetadataRepositoryImpl.java b/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/dao/MetadataRepositoryImpl.java
new file mode 100644
index 0000000..79a7259
--- /dev/null
+++ b/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/dao/MetadataRepositoryImpl.java
@@ -0,0 +1,119 @@
+package org.liuxp.minioplus.application.schedule.dao;
+
+
+import cn.hutool.core.text.CharSequenceUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.liuxp.minioplus.api.model.dto.FileMetadataInfoDTO;
+import org.liuxp.minioplus.api.model.dto.FileMetadataInfoSaveDTO;
+import org.liuxp.minioplus.api.model.dto.FileMetadataInfoUpdateDTO;
+import org.liuxp.minioplus.api.model.vo.FileMetadataInfoVo;
+import org.liuxp.minioplus.application.schedule.entity.FileMetadataInfoEntity;
+import org.liuxp.minioplus.application.schedule.mapper.FileMetadataInfoMapper;
+import org.liuxp.minioplus.core.repository.MetadataRepository;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 文件元数据接口实现类
+ *
+ * @author contact@liuxp.me
+ * @since 2024/05/22
+ */
+@Slf4j
+@Service
+public class MetadataRepositoryImpl extends ServiceImpl implements MetadataRepository {
+
+ @Override
+ public List list(FileMetadataInfoDTO searchDTO) {
+
+ // 组装查询参数
+ QueryWrapper queryWrapper = buildParams(searchDTO);
+
+ List fileMetadataInfoEntityList = super.list(queryWrapper);
+
+ List fileMetadataInfoVoList = new ArrayList<>();
+
+ for (FileMetadataInfoEntity fileMetadataInfoEntity : fileMetadataInfoEntityList) {
+ FileMetadataInfoVo fileMetadataInfoVo = new FileMetadataInfoVo();
+ BeanUtils.copyProperties(fileMetadataInfoEntity, fileMetadataInfoVo);
+ fileMetadataInfoVoList.add(fileMetadataInfoVo);
+ }
+
+ return fileMetadataInfoVoList;
+ }
+
+ @Override
+ public FileMetadataInfoVo one(FileMetadataInfoDTO searchDTO) {
+
+ // 组装查询参数
+ QueryWrapper queryWrapper = buildParams(searchDTO);
+ queryWrapper.last("limit 1");
+
+ FileMetadataInfoEntity fileMetadataInfoEntity = super.getOne(queryWrapper);
+
+ FileMetadataInfoVo fileMetadataInfoVo = new FileMetadataInfoVo();
+
+ if(null!=fileMetadataInfoEntity){
+ BeanUtils.copyProperties(fileMetadataInfoEntity, fileMetadataInfoVo);
+ }
+
+ return fileMetadataInfoVo;
+ }
+
+ @Override
+ public FileMetadataInfoVo save(FileMetadataInfoSaveDTO saveDTO) {
+
+ FileMetadataInfoEntity fileMetadataInfoEntity = new FileMetadataInfoEntity();
+ BeanUtils.copyProperties(saveDTO, fileMetadataInfoEntity);
+ fileMetadataInfoEntity.setCreateTime(new Date());
+ fileMetadataInfoEntity.setUpdateTime(new Date());
+
+ boolean result = super.save(fileMetadataInfoEntity);
+
+ FileMetadataInfoVo fileMetadataInfoVo = new FileMetadataInfoVo();
+ if(result){
+ BeanUtils.copyProperties(fileMetadataInfoEntity, fileMetadataInfoVo);
+ }
+
+ return fileMetadataInfoVo;
+ }
+
+ @Override
+ public FileMetadataInfoVo update(FileMetadataInfoUpdateDTO updateDTO) {
+
+ FileMetadataInfoEntity fileMetadataInfoEntity = new FileMetadataInfoEntity();
+ BeanUtils.copyProperties(updateDTO, fileMetadataInfoEntity);
+ fileMetadataInfoEntity.setUpdateTime(new Date());
+ boolean result = super.updateById(fileMetadataInfoEntity);
+
+ FileMetadataInfoVo fileMetadataInfoVo = new FileMetadataInfoVo();
+ if(result){
+ BeanUtils.copyProperties(fileMetadataInfoEntity, fileMetadataInfoVo);
+ }
+
+ return fileMetadataInfoVo;
+ }
+
+ @Override
+ public Boolean remove(Long id) {
+ return super.removeById(id);
+ }
+
+ private QueryWrapper buildParams(FileMetadataInfoDTO searchDTO){
+ // 组装查询参数
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq(CharSequenceUtil.isNotBlank(searchDTO.getFileKey()),"file_key",searchDTO.getFileKey());
+ queryWrapper.eq(CharSequenceUtil.isNotBlank(searchDTO.getFileMd5()),"file_md5",searchDTO.getFileMd5());
+ queryWrapper.eq(CharSequenceUtil.isNotBlank(searchDTO.getBucket()),"bucket",searchDTO.getBucket());
+ queryWrapper.eq(null!=searchDTO.getIsPrivate(),"is_private",searchDTO.getIsPrivate());
+ queryWrapper.eq(CharSequenceUtil.isNotBlank(searchDTO.getCreateUser()),"create_user",searchDTO.getCreateUser());
+
+ return queryWrapper;
+ }
+}
diff --git a/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/entity/FileMetadataInfoEntity.java b/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/entity/FileMetadataInfoEntity.java
new file mode 100644
index 0000000..11bcf9e
--- /dev/null
+++ b/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/entity/FileMetadataInfoEntity.java
@@ -0,0 +1,101 @@
+package org.liuxp.minioplus.application.schedule.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.Date;
+
+/**
+ * 文件元数据信息表Entity
+ * @author contact@liuxp.me
+ * @since 2024-05-22
+ **/
+@Getter
+@Setter
+@ToString
+@TableName(value = "file_metadata_info")
+public class FileMetadataInfoEntity {
+
+ @TableId(value = "id", type = IdType.AUTO)
+ @ApiModelProperty("主键")
+ private Long id;
+
+ @ApiModelProperty("文件KEY")
+ @TableField(value = "file_key")
+ private String fileKey;
+
+ @ApiModelProperty("文件md5")
+ @TableField(value = "file_md5")
+ private String fileMd5;
+
+ @ApiModelProperty("文件名")
+ @TableField(value = "file_name")
+ private String fileName;
+
+ @ApiModelProperty("MIME类型")
+ @TableField(value = "file_mime_type")
+ private String fileMimeType;
+
+ @ApiModelProperty("文件后缀")
+ @TableField(value = "file_suffix")
+ private String fileSuffix;
+
+ @ApiModelProperty("文件长度")
+ @TableField(value = "file_size")
+ private Long fileSize;
+
+ @ApiModelProperty("预览图 0:无 1:有")
+ @TableField(value = "is_preview")
+ private Boolean isPreview;
+
+ @ApiModelProperty("是否私有 0:否 1:是")
+ @TableField(value = "is_private")
+ private Boolean isPrivate;
+
+ @ApiModelProperty("存储桶")
+ @TableField(value = "bucket")
+ private String storageBucket;
+
+ @ApiModelProperty("存储桶路径")
+ @TableField(value = "bucket_path")
+ private String storagePath;
+
+ @ApiModelProperty("上传任务id,用于合并切片")
+ @TableField(value = "upload_id")
+ private String uploadTaskId;
+
+ @ApiModelProperty("状态 0:未完成 1:已完成")
+ @TableField(value = "is_finished")
+ private Boolean isFinished;
+
+ @ApiModelProperty("是否分块 0:否 1:是")
+ @TableField(value = "is_part")
+ private Boolean isPart;
+
+ @ApiModelProperty("分块数量")
+ @TableField(value = "part_number")
+ private Integer partNumber;
+
+ @ApiModelProperty("创建人")
+ @TableField("create_user")
+ private String createUser;
+
+ @ApiModelProperty("创建时间")
+ @TableField("create_time")
+ private Date createTime;
+
+ @ApiModelProperty("修改人")
+ @TableField("update_user")
+ private String updateUser;
+
+ @ApiModelProperty("修改时间")
+ @TableField("update_time")
+ private Date updateTime;
+
+}
\ No newline at end of file
diff --git a/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/mapper/FileMetadataInfoMapper.java b/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/mapper/FileMetadataInfoMapper.java
new file mode 100644
index 0000000..4219c13
--- /dev/null
+++ b/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/mapper/FileMetadataInfoMapper.java
@@ -0,0 +1,15 @@
+package org.liuxp.minioplus.application.schedule.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.liuxp.minioplus.application.schedule.entity.FileMetadataInfoEntity;
+
+/**
+ * 文件元数据信息表Mapper
+ * @author contact@liuxp.me
+ * @since 2024/05/22
+ */
+@Mapper
+public interface FileMetadataInfoMapper extends BaseMapper {
+
+}
\ No newline at end of file
diff --git a/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/task/CleanTask.java b/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/task/CleanTask.java
new file mode 100644
index 0000000..14865a4
--- /dev/null
+++ b/minio-plus-application/minio-plus-application-schedule/src/main/java/org/liuxp/minioplus/application/schedule/task/CleanTask.java
@@ -0,0 +1,40 @@
+package org.liuxp.minioplus.application.schedule.task;
+
+import lombok.extern.slf4j.Slf4j;
+import org.liuxp.minioplus.api.StorageService;
+import org.liuxp.minioplus.api.model.dto.FileMetadataInfoDTO;
+import org.liuxp.minioplus.api.model.vo.FileMetadataInfoVo;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 定时任务,演示工程定期清理文件
+ * @author contact@liuxp.me
+ * @since 2024/06/17
+ */
+@Component
+@Slf4j
+public class CleanTask {
+
+ @Resource
+ private StorageService storageService;
+
+ @Scheduled(cron = "0 */1 * * * ?")
+ public void clean(){
+
+ List fileList = storageService.list(new FileMetadataInfoDTO());
+
+ for (FileMetadataInfoVo infoVo : fileList) {
+ log.info("文件清理,文件key="+infoVo.getFileKey());
+ try{
+ storageService.remove(infoVo.getFileKey());
+ }catch (Exception e){
+ log.error(infoVo.getFileKey()+"文件清理失败",e);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/minio-plus-application/minio-plus-application-schedule/src/main/resources/application.yml b/minio-plus-application/minio-plus-application-schedule/src/main/resources/application.yml
new file mode 100644
index 0000000..5a640f7
--- /dev/null
+++ b/minio-plus-application/minio-plus-application-schedule/src/main/resources/application.yml
@@ -0,0 +1,69 @@
+spring:
+ #应用唯一标识
+ application:
+ name: MinIOPlus
+ #配置文件
+ profiles:
+ active: dev
+ # 解决Feign接口名称重复报错问题
+ main:
+ allow-bean-definition-overriding: true
+ #jdk proxy
+ aop:
+ proxy-target-class: false
+ auto: false
+ jackson:
+ date-format: yyyy-MM-dd HH:mm:ss
+ time-zone: GMT+8
+ default-property-inclusion: non_null # 全局jackson配置
+ mvc:
+ # 放开 Spring Boot 项目中 /static 目录下静态资源的拦截
+ static-path-pattern: /static/**
+ pathmatch:
+ # Springfox使用的路径匹配是基于AntPathMatcher的,而Spring Boot 2.6.X使用的是PathPatternMatcher所以需要配置此参数
+ matching-strategy: ant_path_matcher
+ #数据源配置
+ datasource:
+ #驱动名称
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ #链接地址
+ url: jdbc:mysql://192.168.50.141:3306/minio-plus?characterEncoding=UTF-8&useSSL=true&serverTimezone=Asia/Shanghai
+ #用户名
+ username: minio
+ #密码
+ password: minioadmin
+##################################################################
+# 服务器
+##################################################################
+server:
+ port: 9010
+##################################################################
+### MinIO Plus Config
+##################################################################
+minioplus:
+ # MinIO 部署地址
+ backend: http://localhost:9000
+ # 浏览器访问地址,文件、图片上传下载访问地址代理,如果minio被nginx代理,需要配置这个参数为代理后的前端访问地址
+ browser-url: http://localhost:9000
+ # 授权key
+ key: minioadmin
+ # 密钥
+ secret: minioadmin
+ # 上传预签名URL有效期,单位为分钟,可选参数,默认值为60分钟
+ upload-expiry: 120
+ # 下载和预览预签名URL有效期,单位为分钟,可选参数,默认值为60分钟
+ download-expiry: 20
+ # 可选参数,分块配置
+ part:
+ # 可选参数,是否开启分块能力。默认为true
+ enable: true
+ # 可选参数,分块大小,配置单位为byte,默认为5242880
+ size: 5242880
+ # 可选参数,分块上传时建议并发数,默认为3
+ iis: 2
+ # 可选参数,缩略图配置
+ thumbnail:
+ # 可选参数,是否开启缩略图。默认为true
+ enable: true
+ # 可选参数,缩略图尺寸,默认为300
+ size: 300
\ No newline at end of file
diff --git a/minio-plus-application/pom.xml b/minio-plus-application/pom.xml
index 2b244bb..d41964e 100644
--- a/minio-plus-application/pom.xml
+++ b/minio-plus-application/pom.xml
@@ -14,6 +14,7 @@
minio-plus-application-mysql
+ minio-plus-application-schedule
\ No newline at end of file
diff --git a/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/pom.xml b/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/pom.xml
new file mode 100644
index 0000000..0538ea2
--- /dev/null
+++ b/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/pom.xml
@@ -0,0 +1,26 @@
+
+
+
+ minio-plus-spring-boot-starter
+ me.liuxp
+ ${revision}
+
+ 4.0.0
+
+ minio-plus-core-spring-boot-starter
+ jar
+
+
+
+ me.liuxp
+ minio-plus-core
+
+
+ me.liuxp
+ minio-s3-api-official
+
+
+
+
\ No newline at end of file
diff --git a/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/java/org/liuxp/minioplus/common/config/MinioPlusAutoConfiguration.java b/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/java/org/liuxp/minioplus/common/config/MinioPlusAutoConfiguration.java
new file mode 100644
index 0000000..80583f5
--- /dev/null
+++ b/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/java/org/liuxp/minioplus/common/config/MinioPlusAutoConfiguration.java
@@ -0,0 +1,14 @@
+package org.liuxp.minioplus.common.config;
+
+import org.springframework.context.annotation.ComponentScan;
+
+/**
+ * MinioPlusAutoConfiguration
+ *
+ * @author contact@liuxp.me
+ * @since 2024/06/11
+ */
+@ComponentScan("org.liuxp.minioplus")
+public class MinioPlusAutoConfiguration {
+
+}
\ No newline at end of file
diff --git a/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/resources/META-INF/spring.factories b/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..a149910
--- /dev/null
+++ b/minio-plus-spring-boot-starter/minio-plus-core-spring-boot-starter/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ org.liuxp.minioplus.common.config.MinioPlusAutoConfiguration
\ No newline at end of file
diff --git a/minio-plus-spring-boot-starter/pom.xml b/minio-plus-spring-boot-starter/pom.xml
index acca8cf..380c091 100644
--- a/minio-plus-spring-boot-starter/pom.xml
+++ b/minio-plus-spring-boot-starter/pom.xml
@@ -14,6 +14,7 @@
minio-plus-all-spring-boot-starter
+ minio-plus-core-spring-boot-starter
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index a9b90c6..d461322 100644
--- a/pom.xml
+++ b/pom.xml
@@ -147,6 +147,11 @@
minio-plus-all-spring-boot-starter
${revision}
+
+ me.liuxp
+ minio-plus-core-spring-boot-starter
+ ${revision}
+
me.liuxp
minio-s3-api-definition
@@ -217,6 +222,7 @@
minio-plus-application
minio-plus-application-mysql
+ minio-plus-application-schedule