mirror of
https://gitee.com/y_project/RuoYi-Cloud.git
synced 2026-01-26 11:51:55 +08:00
文件存储时记录数据库
This commit is contained in:
@@ -16,8 +16,8 @@
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- SpringCloud Alibaba Nacos -->
|
||||
|
||||
<!-- SpringCloud Alibaba Nacos -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
@@ -46,7 +46,7 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- FastDFS -->
|
||||
<dependency>
|
||||
<groupId>com.github.tobato</groupId>
|
||||
@@ -65,12 +65,30 @@
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-api-system</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Mysql Connector -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- RuoYi Common Swagger -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-swagger</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- RuoYi Common Services -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-services</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- RuoYi Common Datasource-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-datasource</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -8,16 +8,14 @@ import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
|
||||
|
||||
/**
|
||||
* 文件服务
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@ConditionalOnProperty(name = "spring.cloud.nacos.config.group", havingValue = "DEFAULT_GROUP", matchIfMissing = true)
|
||||
@EnableCustomSwagger2
|
||||
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
|
||||
public class RuoYiFileApplication
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
|
||||
public class RuoYiFileApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(RuoYiFileApplication.class, args);
|
||||
System.out.println("(♥◠‿◠)ノ゙ 文件服务模块启动成功 ლ(´ڡ`ლ)゙");
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.ruoyi.system.api.domain.SysFile;
|
||||
*/
|
||||
@RestController
|
||||
public class SysFileController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SysFileController.class);
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -4,17 +4,16 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 文件上传接口
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface ISysFileService
|
||||
{
|
||||
public interface ISysFileService {
|
||||
/**
|
||||
* 文件上传接口
|
||||
*
|
||||
*
|
||||
* @param file 上传的文件
|
||||
* @return 访问地址
|
||||
* @throws Exception
|
||||
*/
|
||||
public String uploadFile(MultipartFile file) throws Exception;
|
||||
String uploadFile(MultipartFile file) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
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.utils.FileUploadUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.ruoyi.file.utils.FileUploadUtils;
|
||||
|
||||
/**
|
||||
* 本地文件存储
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Primary
|
||||
@Service
|
||||
public class LocalSysFileServiceImpl implements ISysFileService
|
||||
{
|
||||
public class LocalSysFileServiceImpl implements ISysFileService {
|
||||
/**
|
||||
* 资源映射路径 前缀
|
||||
*/
|
||||
@@ -26,25 +31,45 @@ public class LocalSysFileServiceImpl implements ISysFileService
|
||||
*/
|
||||
@Value("${file.domain}")
|
||||
public String domain;
|
||||
|
||||
|
||||
/**
|
||||
* 上传文件存储在本地的根路径
|
||||
*/
|
||||
@Value("${file.path}")
|
||||
private String localFilePath;
|
||||
|
||||
@Autowired
|
||||
private SysFileMapper sysFileMapper;
|
||||
|
||||
/**
|
||||
* 本地文件上传接口
|
||||
*
|
||||
*
|
||||
* @param file 上传的文件
|
||||
* @return 访问地址
|
||||
* @throws Exception
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public String uploadFile(MultipartFile file) throws Exception
|
||||
{
|
||||
String name = FileUploadUtils.upload(localFilePath, file);
|
||||
String url = domain + localFilePrefix + name;
|
||||
public String uploadFile(MultipartFile file) throws Exception {
|
||||
// 保存文件到本地
|
||||
FileUploadResult uploadResult = FileUploadUtils.upload(localFilePath, file);
|
||||
String savedPathFileName = uploadResult.getSavedPathFileName();
|
||||
String url = domain + localFilePrefix + savedPathFileName;
|
||||
// 保存文件记录
|
||||
saveFileRecord(url, uploadResult);
|
||||
// 返回访问地址
|
||||
return url;
|
||||
}
|
||||
|
||||
private void saveFileRecord(String requestUrl, FileUploadResult uploadResult) {
|
||||
SysFile record = new SysFile();
|
||||
record.setFileId(uploadResult.getFileId()); // 文件ID
|
||||
record.setSavedName(uploadResult.getSavedFileName()); // 保存的文件名
|
||||
record.setOriginalName(uploadResult.getOriginalFilename()); // 原文件名
|
||||
record.setFilePath(uploadResult.getSavedPath()); // 本地保存的文件路径
|
||||
record.setExtension(uploadResult.getExtension()); // 文件扩展名
|
||||
record.setStorageType(FileStorageType.LOCAL.name()); // 存储类型:本地文件存储
|
||||
record.setRequestUrl(requestUrl); // 获取文件的URL
|
||||
record.setFileSize(uploadResult.getFileSize()); // 文件大小(Byte)
|
||||
sysFileMapper.insertSelective(record);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
package com.ruoyi.file.service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.ruoyi.file.config.MinioConfig;
|
||||
import com.ruoyi.file.utils.FileUploadUtils;
|
||||
import io.minio.MinioClient;
|
||||
import io.minio.PutObjectArgs;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* TODO 未完成,还需要保存文件记录
|
||||
* Minio 文件存储
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service
|
||||
public class MinioSysFileServiceImpl implements ISysFileService
|
||||
{
|
||||
public class MinioSysFileServiceImpl implements ISysFileService {
|
||||
@Autowired
|
||||
private MinioConfig minioConfig;
|
||||
|
||||
@@ -29,12 +30,10 @@ public class MinioSysFileServiceImpl implements ISysFileService
|
||||
*
|
||||
* @param file 上传的文件
|
||||
* @return 访问地址
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public String uploadFile(MultipartFile file) throws Exception
|
||||
{
|
||||
String fileName = FileUploadUtils.extractFilename(file);
|
||||
public String uploadFile(MultipartFile file) throws Exception {
|
||||
String fileName = FileUploadUtils.extractFilename(file, null);
|
||||
InputStream inputStream = file.getInputStream();
|
||||
PutObjectArgs args = PutObjectArgs.builder()
|
||||
.bucket(minioConfig.getBucketName())
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.ruoyi.file.utils;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Alan Scipio
|
||||
* created on 2024/2/19
|
||||
*/
|
||||
@Data
|
||||
public class FileUploadResult implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String fileId;
|
||||
|
||||
private String savedFileName;
|
||||
|
||||
private String savedPathFileName;
|
||||
|
||||
private String originalFilename;
|
||||
|
||||
private String extension;
|
||||
|
||||
private Long fileSize;
|
||||
|
||||
private String savedPath;
|
||||
|
||||
}
|
||||
@@ -1,12 +1,5 @@
|
||||
package com.ruoyi.file.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.ruoyi.common.core.exception.file.FileException;
|
||||
import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException;
|
||||
import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
|
||||
@@ -16,6 +9,12 @@ 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;
|
||||
|
||||
/**
|
||||
* 文件上传工具类
|
||||
@@ -24,9 +23,9 @@ import com.ruoyi.common.core.utils.uuid.Seq;
|
||||
*/
|
||||
public class FileUploadUtils {
|
||||
/**
|
||||
* 默认大小 50M
|
||||
* 默认大小 100M
|
||||
*/
|
||||
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
|
||||
public static final long DEFAULT_MAX_SIZE = 100 * 1024 * 1024;
|
||||
|
||||
/**
|
||||
* 默认的文件名最大长度 100
|
||||
@@ -38,9 +37,9 @@ public class FileUploadUtils {
|
||||
*
|
||||
* @param baseDir 相对应用的基目录
|
||||
* @param file 上传的文件
|
||||
* @return 文件名称
|
||||
* @return 文件上传结果
|
||||
*/
|
||||
public static String upload(String baseDir, MultipartFile file) throws IOException {
|
||||
public static FileUploadResult upload(String baseDir, MultipartFile file) throws IOException {
|
||||
try {
|
||||
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
|
||||
} catch (FileException fe) {
|
||||
@@ -62,29 +61,39 @@ public class FileUploadUtils {
|
||||
* @throws IOException 比如读写文件出错时
|
||||
* @throws InvalidExtensionException 文件校验异常
|
||||
*/
|
||||
public static String 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
assertAllowed(file, allowedExtension);
|
||||
FileUploadResult result = new FileUploadResult();
|
||||
|
||||
String fileName = extractFilename(file);
|
||||
assertAllowed(file, allowedExtension, result);
|
||||
|
||||
String fileName = extractFilename(file, result);
|
||||
|
||||
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
|
||||
file.transferTo(Paths.get(absPath));
|
||||
return getPathFileName(fileName);
|
||||
String savedPathFileName = getPathFileName(fileName);
|
||||
|
||||
result.setSavedPathFileName(savedPathFileName);
|
||||
result.setSavedPath(absPath);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码文件名
|
||||
* 编码文件名,最终结果举例: .../2024/02/19/20240219154651A001.jpg
|
||||
*/
|
||||
public static String extractFilename(MultipartFile file) {
|
||||
return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
|
||||
FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), FileTypeUtils.getExtension(file));
|
||||
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")
|
||||
@@ -100,26 +109,29 @@ public class FileUploadUtils {
|
||||
}
|
||||
|
||||
private static String getPathFileName(String fileName) {
|
||||
String pathFileName = "/" + fileName;
|
||||
return pathFileName;
|
||||
return "/" + fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件大小校验
|
||||
*
|
||||
* @param file 上传的文件
|
||||
* @param file 上传的文件
|
||||
* @param result 文件上传结果
|
||||
* @throws FileSizeLimitExceededException 如果超出最大大小
|
||||
* @throws InvalidExtensionException 文件校验异常
|
||||
*/
|
||||
public static void assertAllowed(MultipartFile file, String[] allowedExtension)
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user