添加文件存储记录和序列号生成规则的操作画面

This commit is contained in:
AlanScipio
2024-02-20 13:27:51 +08:00
parent eae6443f11
commit e4a49e6b1c
39 changed files with 1699 additions and 531 deletions

View File

@@ -0,0 +1,28 @@
package com.ruoyi.file.constants;
import com.ruoyi.common.core.constant.IEnum;
import lombok.Getter;
/**
* @author Alan Scipio
* created on 2024/2/19
*/
@Getter
public enum FileStorageType implements IEnum {
LOCAL(1, "本地文件存储"),
FAST_DFS(2, "FastDFS文件存储"),
MINIO(3, "MinIO文件存储"),
;
private final int code;
private final String name;
FileStorageType(int code, String name) {
this.code = code;
this.name = name;
}
}

View File

@@ -0,0 +1,58 @@
package com.ruoyi.file.controller;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.file.domain.SysFile;
import com.ruoyi.file.service.ISysFileCRUDService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 文件存储记录Controller
*
* @author ryas
* created on 2024-02-19
*/
@RestController
@RequestMapping("/FileRecord")
public class SysFileCRUDController extends BaseController {
@Autowired
private ISysFileCRUDService crudService;
/**
* 查询文件存储记录列表
*/
@RequiresPermissions("file:FileRecord:list")
@GetMapping("/list")
public TableDataInfo list(SysFile sysFile) {
startPage();
List<SysFile> list = crudService.selectSysFileList(sysFile);
return getDataTable(list);
}
/**
* 导出文件存储记录列表
*/
@RequiresPermissions("file:FileRecord:export")
@PostMapping("/export")
public void export(HttpServletResponse response, SysFile sysFile) {
List<SysFile> list = crudService.selectSysFileList(sysFile);
ExcelUtil<SysFile> util = new ExcelUtil<>(SysFile.class);
util.exportExcel(response, list, "文件存储记录数据");
}
/**
* 获取文件存储记录详细信息
*/
@RequiresPermissions("file:FileRecord:query")
@GetMapping(value = "/{fileId}")
public AjaxResult getInfo(@PathVariable("fileId") String fileId) {
return success(crudService.selectSysFileByFileId(fileId));
}
}

View File

@@ -1,5 +1,6 @@
package com.ruoyi.file.controller;
import com.ruoyi.file.domain.FileSaveResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -9,7 +10,7 @@ import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.service.ISysFileService;
import com.ruoyi.system.api.domain.SysFile;
import com.ruoyi.system.api.domain.SysFileInfo;
/**
* 文件请求处理
@@ -28,14 +29,17 @@ public class SysFileController {
* 文件上传请求
*/
@PostMapping("upload")
public R<SysFile> upload(MultipartFile file) {
public R<SysFileInfo> upload(MultipartFile file) {
try {
// 上传并返回访问地址
String url = sysFileService.uploadFile(file);
SysFile sysFile = new SysFile();
sysFile.setName(FileUtils.getName(url));
sysFile.setUrl(url);
return R.ok(sysFile);
FileSaveResult saveResult = sysFileService.uploadFile(file);
String requestUrl = saveResult.getRequestUrl();
// 构建返回结果
SysFileInfo responseInfo = new SysFileInfo();
responseInfo.setFileId(saveResult.getFileId());
responseInfo.setName(FileUtils.getName(requestUrl));
responseInfo.setUrl(requestUrl);
return R.ok(responseInfo);
} catch (Exception e) {
log.error("上传文件失败", e);
return R.fail(e.getMessage());

View File

@@ -0,0 +1,43 @@
package com.ruoyi.file.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.web.multipart.MultipartFile;
import java.io.Serial;
import java.io.Serializable;
/**
* @author Alan Scipio
* created on 2024/2/19
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class FileSaveForm implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 域名或本机访问地址
*/
public String domain;
/**
* 文件存储基础目录
*/
private String localBaseDir;
/**
* 资源映射路径 前缀
*/
public String localFilePrefix;
/**
* 上传的文件
*/
private MultipartFile file;
}

View File

@@ -1,23 +0,0 @@
package com.ruoyi.file.domain;
import com.ruoyi.file.utils.FileUploadResult;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author Alan Scipio
* created on 2024/2/19
*/
@Data
public class FileSaveRecord implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String requestUrl;
private FileUploadResult uploadResult;
}

View File

@@ -0,0 +1,51 @@
package com.ruoyi.file.domain;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author Alan Scipio
* created on 2024/2/19
*/
@Data
public class FileSaveResult implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private boolean success;
private String message;
/**
* 文件请求地址
*/
private String requestUrl;
/**
* 文件上传结果
*/
private FileUploadResult uploadResult;
public String getFileId() {
return uploadResult == null ? "" : uploadResult.getFileId();
}
public static FileSaveResult success(String requestUrl, FileUploadResult uploadResult) {
FileSaveResult result = new FileSaveResult();
result.setSuccess(true);
result.setRequestUrl(requestUrl);
result.setUploadResult(uploadResult);
return result;
}
public static FileSaveResult fail(String message) {
FileSaveResult result = new FileSaveResult();
result.setSuccess(false);
result.setMessage(message);
return result;
}
}

View File

@@ -1,4 +1,4 @@
package com.ruoyi.file.utils;
package com.ruoyi.file.domain;
import lombok.Data;
@@ -15,18 +15,39 @@ public class FileUploadResult implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 文件ID
*/
private String fileId;
/**
* 存储的文件名
*/
private String savedFileName;
/**
* 存储的文件名带年月日的相对父路径例如/2024/02/19/xxx.png
*/
private String savedPathFileName;
/**
* 原始文件名
*/
private String originalFilename;
/**
* 文件扩展名
*/
private String extension;
/**
* 文件大小
*/
private Long fileSize;
/**
* 文件存储的绝对路径
*/
private String savedPath;
}

View File

@@ -0,0 +1,154 @@
package com.ruoyi.file.domain;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import java.io.Serial;
import java.io.Serializable;
/**
* This class was generated by MyBatis Generator.
*
* <ul>
* <li> Table: sys_file </li>
* <li> Remarks: 文件存储记录表 </li>
* </ul>
*
* @author ryas
* created on 2024-02-19
*/
public class SysFile extends BaseEntity implements Serializable {
/**
* 文件ID
*/
@Excel(name = "文件ID")
private String fileId;
/**
* 保存的文件名称
*/
@Excel(name = "保存文件名")
private String savedName;
/**
* 原始文件名称
*/
@Excel(name = "原始文件名")
private String originalName;
/**
* 文件路径
*/
@Excel(name = "文件路径")
private String filePath;
/**
* 文件后缀
*/
@Excel(name = "文件后缀")
private String extension;
/**
* 存储方式
*/
@Excel(name = "存储方式")
private String storageType;
/**
* 获取文件的URL
*/
@Excel(name = "获取文件的URL")
private String requestUrl;
/**
* 文件大小(Byte)
*/
@Excel(name = "文件大小(Byte)")
private Long fileSize;
@Serial
private static final long serialVersionUID = 1L;
public String getFileId() {
return fileId;
}
public void setFileId(String fileId) {
this.fileId = fileId == null ? null : fileId.trim();
}
public String getSavedName() {
return savedName;
}
public void setSavedName(String savedName) {
this.savedName = savedName == null ? null : savedName.trim();
}
public String getOriginalName() {
return originalName;
}
public void setOriginalName(String originalName) {
this.originalName = originalName == null ? null : originalName.trim();
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath == null ? null : filePath.trim();
}
public String getExtension() {
return extension;
}
public void setExtension(String extension) {
this.extension = extension == null ? null : extension.trim();
}
public String getStorageType() {
return storageType;
}
public void setStorageType(String storageType) {
this.storageType = storageType == null ? null : storageType.trim();
}
public String getRequestUrl() {
return requestUrl;
}
public void setRequestUrl(String requestUrl) {
this.requestUrl = requestUrl == null ? null : requestUrl.trim();
}
public Long getFileSize() {
return fileSize;
}
public void setFileSize(Long fileSize) {
this.fileSize = fileSize;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", fileId=").append(fileId);
sb.append(", savedName=").append(savedName);
sb.append(", originalName=").append(originalName);
sb.append(", filePath=").append(filePath);
sb.append(", extension=").append(extension);
sb.append(", storageType=").append(storageType);
sb.append(", requestUrl=").append(requestUrl);
sb.append(", fileSize=").append(fileSize);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();
}
}

View File

@@ -0,0 +1,108 @@
package com.ruoyi.file.mapper;
import org.mybatis.dynamic.sql.AliasableSqlTable;
import org.mybatis.dynamic.sql.SqlColumn;
import java.sql.JDBCType;
import java.util.Date;
public final class SysFileDynamicSqlSupport {
public static final SysFile sysFile = new SysFile();
/**
* 文件ID
*/
public static final SqlColumn<String> fileId = sysFile.fileId;
/**
* 保存的文件名称
*/
public static final SqlColumn<String> savedName = sysFile.savedName;
/**
* 原始文件名称
*/
public static final SqlColumn<String> originalName = sysFile.originalName;
/**
* 文件路径
*/
public static final SqlColumn<String> filePath = sysFile.filePath;
/**
* 文件后缀
*/
public static final SqlColumn<String> extension = sysFile.extension;
/**
* 存储方式
*/
public static final SqlColumn<String> storageType = sysFile.storageType;
/**
* 获取文件的URL
*/
public static final SqlColumn<String> requestUrl = sysFile.requestUrl;
/**
* 文件大小(Byte)
*/
public static final SqlColumn<Long> fileSize = sysFile.fileSize;
/**
* 创建者
*/
public static final SqlColumn<String> createBy = sysFile.createBy;
/**
* 创建时间
*/
public static final SqlColumn<Date> createTime = sysFile.createTime;
/**
* 更新者
*/
public static final SqlColumn<String> updateBy = sysFile.updateBy;
/**
* 更新时间
*/
public static final SqlColumn<Date> updateTime = sysFile.updateTime;
/**
* 备注
*/
public static final SqlColumn<String> remark = sysFile.remark;
public static final class SysFile extends AliasableSqlTable<SysFile> {
public final SqlColumn<String> fileId = column("file_id", JDBCType.VARCHAR);
public final SqlColumn<String> savedName = column("saved_name", JDBCType.VARCHAR);
public final SqlColumn<String> originalName = column("original_name", JDBCType.VARCHAR);
public final SqlColumn<String> filePath = column("file_path", JDBCType.VARCHAR);
public final SqlColumn<String> extension = column("extension", JDBCType.VARCHAR);
public final SqlColumn<String> storageType = column("storage_type", JDBCType.VARCHAR);
public final SqlColumn<String> requestUrl = column("request_url", JDBCType.VARCHAR);
public final SqlColumn<Long> fileSize = column("file_size", JDBCType.BIGINT);
public final SqlColumn<String> createBy = column("create_by", JDBCType.VARCHAR);
public final SqlColumn<Date> createTime = column("create_time", JDBCType.TIMESTAMP);
public final SqlColumn<String> updateBy = column("update_by", JDBCType.VARCHAR);
public final SqlColumn<Date> updateTime = column("update_time", JDBCType.TIMESTAMP);
public final SqlColumn<String> remark = column("remark", JDBCType.VARCHAR);
public SysFile() {
super("sys_file", SysFile::new);
}
}
}

View File

@@ -0,0 +1,215 @@
package com.ruoyi.file.mapper;
import com.ruoyi.common.security.utils.SecurityUtilsExt;
import com.ruoyi.file.domain.SysFile;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.dynamic.sql.BasicColumn;
import org.mybatis.dynamic.sql.delete.DeleteDSLCompleter;
import org.mybatis.dynamic.sql.select.CountDSLCompleter;
import org.mybatis.dynamic.sql.select.SelectDSLCompleter;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.mybatis.dynamic.sql.update.UpdateDSL;
import org.mybatis.dynamic.sql.update.UpdateDSLCompleter;
import org.mybatis.dynamic.sql.update.UpdateModel;
import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
import org.mybatis.dynamic.sql.util.mybatis3.*;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import static com.ruoyi.file.mapper.SysFileDynamicSqlSupport.*;
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;
@Mapper
public interface SysFileMapper extends CommonCountMapper, CommonDeleteMapper, CommonInsertMapper<SysFile>, CommonUpdateMapper {
BasicColumn[] selectList = BasicColumn.columnList(fileId, savedName, originalName, filePath, extension, storageType, requestUrl, fileSize, createBy, createTime, updateBy, updateTime, remark);
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@Results(id="SysFileResult", value = {
@Result(column="file_id", property="fileId", jdbcType=JdbcType.VARCHAR, id=true),
@Result(column="saved_name", property="savedName", jdbcType=JdbcType.VARCHAR),
@Result(column="original_name", property="originalName", jdbcType=JdbcType.VARCHAR),
@Result(column="file_path", property="filePath", jdbcType=JdbcType.VARCHAR),
@Result(column="extension", property="extension", jdbcType=JdbcType.VARCHAR),
@Result(column="storage_type", property="storageType", jdbcType=JdbcType.VARCHAR),
@Result(column="request_url", property="requestUrl", jdbcType=JdbcType.VARCHAR),
@Result(column="file_size", property="fileSize", jdbcType=JdbcType.BIGINT),
@Result(column="create_by", property="createBy", jdbcType=JdbcType.VARCHAR),
@Result(column="create_time", property="createTime", jdbcType=JdbcType.TIMESTAMP),
@Result(column="update_by", property="updateBy", jdbcType=JdbcType.VARCHAR),
@Result(column="update_time", property="updateTime", jdbcType=JdbcType.TIMESTAMP),
@Result(column="remark", property="remark", jdbcType=JdbcType.VARCHAR)
})
List<SysFile> selectMany(SelectStatementProvider selectStatement);
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@ResultMap("SysFileResult")
Optional<SysFile> selectOne(SelectStatementProvider selectStatement);
default long count(CountDSLCompleter completer) {
return MyBatis3Utils.countFrom(this::count, sysFile, completer);
}
default int delete(DeleteDSLCompleter completer) {
return MyBatis3Utils.deleteFrom(this::delete, sysFile, completer);
}
default int deleteByPrimaryKey(String fileId_) {
return delete(c ->
c.where(fileId, isEqualTo(fileId_))
);
}
default int insert(SysFile row) {
row.setCommonForInsert(SecurityUtilsExt.getUserIdStr());
return MyBatis3Utils.insert(this::insert, row, sysFile, c ->
c.map(fileId).toProperty("fileId")
.map(savedName).toProperty("savedName")
.map(originalName).toProperty("originalName")
.map(filePath).toProperty("filePath")
.map(extension).toProperty("extension")
.map(storageType).toProperty("storageType")
.map(requestUrl).toProperty("requestUrl")
.map(fileSize).toProperty("fileSize")
.map(createBy).toProperty("createBy")
.map(createTime).toProperty("createTime")
.map(updateBy).toProperty("updateBy")
.map(updateTime).toProperty("updateTime")
.map(remark).toProperty("remark")
);
}
default int insertMultiple(Collection<SysFile> records) {
for (SysFile row : records) {
row.setCommonForInsert(SecurityUtilsExt.getUserIdStr());
}
return MyBatis3Utils.insertMultiple(this::insertMultiple, records, sysFile, c ->
c.map(fileId).toProperty("fileId")
.map(savedName).toProperty("savedName")
.map(originalName).toProperty("originalName")
.map(filePath).toProperty("filePath")
.map(extension).toProperty("extension")
.map(storageType).toProperty("storageType")
.map(requestUrl).toProperty("requestUrl")
.map(fileSize).toProperty("fileSize")
.map(createBy).toProperty("createBy")
.map(createTime).toProperty("createTime")
.map(updateBy).toProperty("updateBy")
.map(updateTime).toProperty("updateTime")
.map(remark).toProperty("remark")
);
}
default int insertSelective(SysFile row) {
row.setCommonForInsert(SecurityUtilsExt.getUserIdStr());
return MyBatis3Utils.insert(this::insert, row, sysFile, c ->
c.map(fileId).toPropertyWhenPresent("fileId", row::getFileId)
.map(savedName).toPropertyWhenPresent("savedName", row::getSavedName)
.map(originalName).toPropertyWhenPresent("originalName", row::getOriginalName)
.map(filePath).toPropertyWhenPresent("filePath", row::getFilePath)
.map(extension).toPropertyWhenPresent("extension", row::getExtension)
.map(storageType).toPropertyWhenPresent("storageType", row::getStorageType)
.map(requestUrl).toPropertyWhenPresent("requestUrl", row::getRequestUrl)
.map(fileSize).toPropertyWhenPresent("fileSize", row::getFileSize)
.map(createBy).toPropertyWhenPresent("createBy", row::getCreateBy)
.map(createTime).toPropertyWhenPresent("createTime", row::getCreateTime)
.map(updateBy).toPropertyWhenPresent("updateBy", row::getUpdateBy)
.map(updateTime).toPropertyWhenPresent("updateTime", row::getUpdateTime)
.map(remark).toPropertyWhenPresent("remark", row::getRemark)
);
}
default Optional<SysFile> selectOne(SelectDSLCompleter completer) {
return MyBatis3Utils.selectOne(this::selectOne, selectList, sysFile, completer);
}
default List<SysFile> select(SelectDSLCompleter completer) {
return MyBatis3Utils.selectList(this::selectMany, selectList, sysFile, completer);
}
default List<SysFile> selectDistinct(SelectDSLCompleter completer) {
return MyBatis3Utils.selectDistinct(this::selectMany, selectList, sysFile, completer);
}
default Optional<SysFile> selectByPrimaryKey(String fileId_) {
return selectOne(c ->
c.where(fileId, isEqualTo(fileId_))
);
}
default int update(UpdateDSLCompleter completer) {
return MyBatis3Utils.update(this::update, sysFile, completer);
}
static UpdateDSL<UpdateModel> updateAllColumns(SysFile row, UpdateDSL<UpdateModel> dsl) {
return dsl.set(fileId).equalTo(row::getFileId)
.set(savedName).equalTo(row::getSavedName)
.set(originalName).equalTo(row::getOriginalName)
.set(filePath).equalTo(row::getFilePath)
.set(extension).equalTo(row::getExtension)
.set(storageType).equalTo(row::getStorageType)
.set(requestUrl).equalTo(row::getRequestUrl)
.set(fileSize).equalTo(row::getFileSize)
.set(createBy).equalTo(row::getCreateBy)
.set(createTime).equalTo(row::getCreateTime)
.set(updateBy).equalTo(row::getUpdateBy)
.set(updateTime).equalTo(row::getUpdateTime)
.set(remark).equalTo(row::getRemark);
}
static UpdateDSL<UpdateModel> updateSelectiveColumns(SysFile row, UpdateDSL<UpdateModel> dsl) {
row.setCommonForUpdate(SecurityUtilsExt.getUserIdStr());
return dsl.set(fileId).equalToWhenPresent(row::getFileId)
.set(savedName).equalToWhenPresent(row::getSavedName)
.set(originalName).equalToWhenPresent(row::getOriginalName)
.set(filePath).equalToWhenPresent(row::getFilePath)
.set(extension).equalToWhenPresent(row::getExtension)
.set(storageType).equalToWhenPresent(row::getStorageType)
.set(requestUrl).equalToWhenPresent(row::getRequestUrl)
.set(fileSize).equalToWhenPresent(row::getFileSize)
.set(createBy).equalToWhenPresent(row::getCreateBy)
.set(createTime).equalToWhenPresent(row::getCreateTime)
.set(updateBy).equalToWhenPresent(row::getUpdateBy)
.set(updateTime).equalToWhenPresent(row::getUpdateTime)
.set(remark).equalToWhenPresent(row::getRemark);
}
default int updateByPrimaryKey(SysFile row) {
return update(c ->
c.set(savedName).equalTo(row::getSavedName)
.set(originalName).equalTo(row::getOriginalName)
.set(filePath).equalTo(row::getFilePath)
.set(extension).equalTo(row::getExtension)
.set(storageType).equalTo(row::getStorageType)
.set(requestUrl).equalTo(row::getRequestUrl)
.set(fileSize).equalTo(row::getFileSize)
.set(createBy).equalTo(row::getCreateBy)
.set(createTime).equalTo(row::getCreateTime)
.set(updateBy).equalTo(row::getUpdateBy)
.set(updateTime).equalTo(row::getUpdateTime)
.set(remark).equalTo(row::getRemark)
.where(fileId, isEqualTo(row::getFileId))
);
}
default int updateByPrimaryKeySelective(SysFile row) {
row.setCommonForUpdate(SecurityUtilsExt.getUserIdStr());
return update(c ->
c.set(savedName).equalToWhenPresent(row::getSavedName)
.set(originalName).equalToWhenPresent(row::getOriginalName)
.set(filePath).equalToWhenPresent(row::getFilePath)
.set(extension).equalToWhenPresent(row::getExtension)
.set(storageType).equalToWhenPresent(row::getStorageType)
.set(requestUrl).equalToWhenPresent(row::getRequestUrl)
.set(fileSize).equalToWhenPresent(row::getFileSize)
.set(createBy).equalToWhenPresent(row::getCreateBy)
.set(createTime).equalToWhenPresent(row::getCreateTime)
.set(updateBy).equalToWhenPresent(row::getUpdateBy)
.set(updateTime).equalToWhenPresent(row::getUpdateTime)
.set(remark).equalToWhenPresent(row::getRemark)
.where(fileId, isEqualTo(row::getFileId))
);
}
}

View File

@@ -1,15 +1,10 @@
package com.ruoyi.file.service;
import java.io.InputStream;
import com.alibaba.nacos.common.utils.IoUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.ruoyi.file.domain.FileSaveResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.ruoyi.common.core.utils.file.FileTypeUtils;
/**
* FastDFS 文件存储
@@ -34,13 +29,12 @@ public class FastDfsSysFileServiceImpl implements ISysFileService {
* @return 访问地址
*/
@Override
public String uploadFile(MultipartFile file) throws Exception {
public FileSaveResult uploadFile(MultipartFile file) throws Exception {
// InputStream inputStream = file.getInputStream();
// StorePath storePath = storageClient.uploadFile(inputStream, file.getSize(),
// FileTypeUtils.getExtension(file), null);
// IoUtils.closeQuietly(inputStream);
// return domain + "/" + storePath.getFullPath();
return "notImplementedYet";
return FileSaveResult.fail("Not implemented yet!");
}
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.file.service;
import com.ruoyi.file.domain.SysFile;
import java.util.List;
/**
* 文件存储记录Service接口
*
* @author ryas
* created on 2024-02-19
*/
public interface ISysFileCRUDService {
/**
* 查询文件存储记录
*
* @param fileId 文件存储记录主键
* @return 文件存储记录
*/
SysFile selectSysFileByFileId(String fileId);
/**
* 查询文件存储记录列表
*
* @param sysFile 文件存储记录
* @return 文件存储记录集合
*/
List<SysFile> selectSysFileList(SysFile sysFile);
/**
* 新增文件存储记录
*
* @param sysFile 文件存储记录
* @return 结果
*/
int insertSysFile(SysFile sysFile);
/**
* 修改文件存储记录
*
* @param sysFile 文件存储记录
* @return 结果
*/
int updateSysFile(SysFile sysFile);
/**
* 批量删除文件存储记录
*
* @param fileIds 需要删除的文件存储记录主键集合
* @return 结果
*/
int deleteSysFileByFileIds(String[] fileIds);
/**
* 删除文件存储记录信息
*
* @param fileId 文件存储记录主键
* @return 结果
*/
int deleteSysFileByFileId(String fileId);
}

View File

@@ -1,5 +1,6 @@
package com.ruoyi.file.service;
import com.ruoyi.file.domain.FileSaveResult;
import org.springframework.web.multipart.MultipartFile;
/**
@@ -12,8 +13,8 @@ public interface ISysFileService {
* 文件上传接口
*
* @param file 上传的文件
* @return 访问地址
* @return 保存结果
*/
String uploadFile(MultipartFile file) throws Exception;
FileSaveResult uploadFile(MultipartFile file) throws Exception;
}

View File

@@ -1,9 +1,10 @@
package com.ruoyi.file.service;
import com.ruoyi.common.services.constants.FileStorageType;
import com.ruoyi.common.services.domain.SysFile;
import com.ruoyi.common.services.mapper.SysFileMapper;
import com.ruoyi.file.utils.FileUploadResult;
import com.ruoyi.file.constants.FileStorageType;
import com.ruoyi.file.domain.FileSaveResult;
import com.ruoyi.file.domain.FileUploadResult;
import com.ruoyi.file.domain.SysFile;
import com.ruoyi.file.mapper.SysFileMapper;
import com.ruoyi.file.utils.FileUploadUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -49,18 +50,19 @@ public class LocalSysFileServiceImpl implements ISysFileService {
*/
@Transactional
@Override
public String uploadFile(MultipartFile file) throws Exception {
public FileSaveResult uploadFile(MultipartFile file) throws Exception {
// 保存文件到本地
FileUploadResult uploadResult = FileUploadUtils.upload(localFilePath, file);
String savedPathFileName = uploadResult.getSavedPathFileName();
String url = domain + localFilePrefix + savedPathFileName;
String requestUrl = domain + localFilePrefix + savedPathFileName;
// 保存文件记录
saveFileRecord(url, uploadResult);
SysFile record = getSysFile(uploadResult, requestUrl);
sysFileMapper.insertSelective(record);
// 返回访问地址
return url;
return FileSaveResult.success(requestUrl, uploadResult);
}
private void saveFileRecord(String requestUrl, FileUploadResult uploadResult) {
private SysFile getSysFile(FileUploadResult uploadResult, String requestUrl) {
SysFile record = new SysFile();
record.setFileId(uploadResult.getFileId()); // 文件ID
record.setSavedName(uploadResult.getSavedFileName()); // 保存的文件名
@@ -70,6 +72,6 @@ public class LocalSysFileServiceImpl implements ISysFileService {
record.setStorageType(FileStorageType.LOCAL.name()); // 存储类型:本地文件存储
record.setRequestUrl(requestUrl); // 获取文件的URL
record.setFileSize(uploadResult.getFileSize()); // 文件大小(Byte)
sysFileMapper.insertSelective(record);
return record;
}
}

View File

@@ -1,8 +1,9 @@
package com.ruoyi.file.service;
import com.alibaba.nacos.common.utils.IoUtils;
import com.ruoyi.file.config.MinioConfig;
import com.ruoyi.file.domain.FileSaveResult;
import com.ruoyi.file.utils.FileUploadUtils;
import com.ruoyi.file.config.MinioConfig;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.springframework.beans.factory.annotation.Autowired;
@@ -12,7 +13,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
/**
* TODO 未完成,还需要保存文件记录
* TODO 未完成,还需要改造:保存文件记录
* Minio 文件存储
*
* @author ruoyi
@@ -32,7 +33,7 @@ public class MinioSysFileServiceImpl implements ISysFileService {
* @return 访问地址
*/
@Override
public String uploadFile(MultipartFile file) throws Exception {
public FileSaveResult uploadFile(MultipartFile file) throws Exception {
String fileName = FileUploadUtils.extractFilename(file, null);
InputStream inputStream = file.getInputStream();
PutObjectArgs args = PutObjectArgs.builder()
@@ -43,6 +44,7 @@ public class MinioSysFileServiceImpl implements ISysFileService {
.build();
client.putObject(args);
IoUtils.closeQuietly(inputStream);
return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
String requestUrl = minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
return FileSaveResult.success(requestUrl, null);
}
}

View File

@@ -0,0 +1,116 @@
package com.ruoyi.file.service;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.file.domain.SysFile;
import com.ruoyi.file.mapper.SysFileDynamicSqlSupport;
import com.ruoyi.file.mapper.SysFileMapper;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
import org.mybatis.dynamic.sql.render.RenderingStrategies;
import org.mybatis.dynamic.sql.select.SelectDSLCompleter;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
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.Optional;
/**
* 文件存储记录Service业务层处理
*
* @author ryas
* created on 2024-02-19
*/
@Service
public class SysFileCRUDServiceImpl implements ISysFileCRUDService {
@Autowired
private SysFileMapper sysFileMapper;
/**
* 查询文件存储记录
*
* @param fileId 文件存储记录主键
* @return 文件存储记录
*/
@Override
public SysFile selectSysFileByFileId(String fileId) {
Optional<SysFile> result = sysFileMapper.selectOne(dsl -> dsl.where(SysFileDynamicSqlSupport.fileId, SqlBuilder.isEqualTo(fileId)));
return result.orElse(null);
}
/**
* 查询文件存储记录列表
*
* @param sysFile 文件存储记录
* @return 文件存储记录
*/
@Override
public List<SysFile> selectSysFileList(SysFile sysFile) {
if (StringUtils.isNotBlank(sysFile.getSavedName()) || StringUtils.isNotBlank(sysFile.getFileId())) {
//条件查询
SelectStatementProvider provider = SqlBuilder.select(SysFileMapper.selectList)
.from(SysFileDynamicSqlSupport.sysFile)
.where(SysFileDynamicSqlSupport.fileId, SqlBuilder.isEqualToWhenPresent(sysFile.getFileId()))
.and(SysFileDynamicSqlSupport.savedName, SqlBuilder.isLikeWhenPresent(sysFile.getSavedName() == null ? null : "%" + sysFile.getSavedName() + "%"))
.build()
.render(RenderingStrategies.MYBATIS3);
return sysFileMapper.selectMany(provider);
} else {
//全部查询
return sysFileMapper.select(SelectDSLCompleter.allRows());
}
}
/**
* 新增文件存储记录
*
* @param sysFile 文件存储记录
* @return 结果
*/
@Transactional
@Override
public int insertSysFile(SysFile sysFile) {
return sysFileMapper.insertSelective(sysFile);
}
/**
* 修改文件存储记录
*
* @param sysFile 文件存储记录
* @return 结果
*/
@Transactional
@Override
public int updateSysFile(SysFile sysFile) {
return sysFileMapper.updateByPrimaryKeySelective(sysFile);
}
/**
* 批量删除文件存储记录
*
* @param fileIds 需要删除的文件存储记录主键
* @return 结果
*/
@Transactional
@Override
public int deleteSysFileByFileIds(String[] fileIds) {
DeleteStatementProvider provider = SqlBuilder.deleteFrom(SysFileDynamicSqlSupport.sysFile)
.where(SysFileDynamicSqlSupport.fileId, SqlBuilder.isIn(fileIds))
.build()
.render(RenderingStrategies.MYBATIS3);
return sysFileMapper.delete(provider);
}
/**
* 删除文件存储记录信息
*
* @param fileId 文件存储记录主键
* @return 结果
*/
@Transactional
@Override
public int deleteSysFileByFileId(String fileId) {
return sysFileMapper.deleteByPrimaryKey(fileId);
}
}

View File

@@ -1,169 +1,170 @@
package com.ruoyi.file.utils;
import com.ruoyi.common.core.exception.file.FileException;
import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException;
import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
import com.ruoyi.common.core.exception.file.InvalidExtensionException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileTypeUtils;
import com.ruoyi.common.core.utils.file.MimeTypeUtils;
import com.ruoyi.common.core.utils.uuid.Seq;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
/**
* 文件上传工具类
*
* @author ruoyi
*/
public class FileUploadUtils {
/**
* 默认大小 100M
*/
public static final long DEFAULT_MAX_SIZE = 100 * 1024 * 1024;
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件上传结果
*/
public static FileUploadResult upload(String baseDir, MultipartFile file) throws IOException {
try {
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
} catch (FileException fe) {
throw new IOException(fe.getDefaultMessage(), fe);
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static FileUploadResult upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, InvalidExtensionException {
int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
FileUploadResult result = new FileUploadResult();
assertAllowed(file, allowedExtension, result);
String fileName = extractFilename(file, result);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
file.transferTo(Paths.get(absPath));
String savedPathFileName = getPathFileName(fileName);
result.setSavedPathFileName(savedPathFileName);
result.setSavedPath(absPath);
return result;
}
/**
* 编码文件名,最终结果举例: .../2024/02/19/20240219154651A001.jpg
*/
public static String extractFilename(MultipartFile file, FileUploadResult result) {
String fileId = Seq.getId(Seq.uploadSeqType);
String savedFileName = StringUtils.format("{}.{}", fileId, FileTypeUtils.getExtension(file));
if (result != null) {
result.setFileId(fileId);
result.setSavedFileName(savedFileName);
}
return StringUtils.format("{}/{}", DateUtils.datePath(), savedFileName);
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private static File getAbsoluteFile(String uploadDir, String fileName) {
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists()) {
if (!desc.getParentFile().exists()) {
desc.getParentFile().mkdirs();
}
}
return desc.isAbsolute() ? desc : desc.getAbsoluteFile();
}
private static String getPathFileName(String fileName) {
return "/" + fileName;
}
/**
* 文件大小校验
*
* @param file 上传的文件
* @param result 文件上传结果
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws InvalidExtensionException 文件校验异常
*/
public static void assertAllowed(MultipartFile file, String[] allowedExtension, FileUploadResult result)
throws FileSizeLimitExceededException, InvalidExtensionException {
long size = file.getSize();
if (size > DEFAULT_MAX_SIZE) {
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
result.setFileSize(size);
String fileName = file.getOriginalFilename();
String extension = FileTypeUtils.getExtension(file);
result.setExtension(extension);
result.setOriginalFilename(fileName);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) {
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) {
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) {
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) {
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
} else {
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 判断MIME类型是否是允许的MIME类型
*
* @param extension 上传文件类型
* @param allowedExtension 允许上传文件类型
* @return true/false
*/
public static boolean isAllowedExtension(String extension, String[] allowedExtension) {
for (String str : allowedExtension) {
if (str.equalsIgnoreCase(extension)) {
return true;
}
}
return false;
}
package com.ruoyi.file.utils;
import com.ruoyi.common.core.exception.file.FileException;
import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException;
import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
import com.ruoyi.common.core.exception.file.InvalidExtensionException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileTypeUtils;
import com.ruoyi.common.core.utils.file.MimeTypeUtils;
import com.ruoyi.common.core.utils.uuid.Seq;
import com.ruoyi.file.domain.FileUploadResult;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
/**
* 文件上传工具类
*
* @author ruoyi
*/
public class FileUploadUtils {
/**
* 默认大小 100M
*/
public static final long DEFAULT_MAX_SIZE = 100 * 1024 * 1024;
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件上传结果
*/
public static FileUploadResult upload(String baseDir, MultipartFile file) throws IOException {
try {
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
} catch (FileException fe) {
throw new IOException(fe.getDefaultMessage(), fe);
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static FileUploadResult upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, InvalidExtensionException {
int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
FileUploadResult result = new FileUploadResult();
assertAllowed(file, allowedExtension, result);
String fileName = extractFilename(file, result);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
file.transferTo(Paths.get(absPath));
String savedPathFileName = getPathFileName(fileName);
result.setSavedPathFileName(savedPathFileName);
result.setSavedPath(absPath);
return result;
}
/**
* 编码文件名,最终结果举例: .../2024/02/19/20240219154651A001.jpg
*/
public static String extractFilename(MultipartFile file, FileUploadResult result) {
String fileId = Seq.getId(Seq.uploadSeqType);
String savedFileName = StringUtils.format("{}.{}", fileId, FileTypeUtils.getExtension(file));
if (result != null) {
result.setFileId(fileId);
result.setSavedFileName(savedFileName);
}
return StringUtils.format("{}/{}", DateUtils.datePath(), savedFileName);
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private static File getAbsoluteFile(String uploadDir, String fileName) {
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists()) {
if (!desc.getParentFile().exists()) {
desc.getParentFile().mkdirs();
}
}
return desc.isAbsolute() ? desc : desc.getAbsoluteFile();
}
private static String getPathFileName(String fileName) {
return "/" + fileName;
}
/**
* 文件大小校验
*
* @param file 上传的文件
* @param result 文件上传结果
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws InvalidExtensionException 文件校验异常
*/
public static void assertAllowed(MultipartFile file, String[] allowedExtension, FileUploadResult result)
throws FileSizeLimitExceededException, InvalidExtensionException {
long size = file.getSize();
if (size > DEFAULT_MAX_SIZE) {
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
result.setFileSize(size);
String fileName = file.getOriginalFilename();
String extension = FileTypeUtils.getExtension(file);
result.setExtension(extension);
result.setOriginalFilename(fileName);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) {
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) {
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) {
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) {
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
} else {
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 判断MIME类型是否是允许的MIME类型
*
* @param extension 上传文件类型
* @param allowedExtension 允许上传文件类型
* @return true/false
*/
public static boolean isAllowedExtension(String extension, String[] allowedExtension) {
for (String str : allowedExtension) {
if (str.equalsIgnoreCase(extension)) {
return true;
}
}
return false;
}
}