Commit ca5af736 authored by liyang's avatar liyang

refactor: 优化文件上传接口,参考ruoyi-vue标准实现

- 使用file.transferTo()替代FileOutputStream写入文件
- 简化getAbsoluteFile方法的目录创建逻辑
- 新增uploadWithUuid方法支持UUID文件命名
- 修改上传路径配置为项目目录
- 更新SysProfileController使用新的上传方法
parent d5fb5d0f
......@@ -128,7 +128,7 @@ public class SysProfileController extends BaseController
if (!file.isEmpty())
{
LoginUser loginUser = getLoginUser();
String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION, true);
String avatar = FileUploadUtils.uploadWithUuid(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
if (userService.updateUserAvatar(loginUser.getUserId(), avatar))
{
String oldAvatar = loginUser.getUser().getAvatar();
......
# 开发环境配置
server:
port: 8081
# Spring配置
spring:
# 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
master:
url: jdbc:mysql://172.28.135.68:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
slave:
enabled: false
initialSize: 5
minIdle: 10
maxActive: 20
maxWait: 60000
connectTimeout: 30000
socketTimeout: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
maxEvictableIdleTimeMillis: 900000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
allow:
url-pattern: /druid/*
login-username: ruoyi
login-password: 123456
filter:
stat:
enabled: true
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
# redis 配置
redis:
enabled: true
host: localhost
port: 6379
database: 0
password:
timeout: 10s
lettuce:
pool:
min-idle: 0
max-idle: 8
max-active: 8
max-wait: -1ms
# 日志配置
logging:
level:
com.ruoyi: debug
org.springframework: warn
# Swagger配置
swagger:
enabled: true
pathMapping: /dev-api
# 防盗链配置
referer:
enabled: false
allowed-domains: localhost,127.0.0.1,172.28.135.68
# 文件路径
ruoyi:
profile: F:/ruoyi/uploadPath
addressEnabled: false
# 生产环境配置
server:
port: 8081
# Spring配置
spring:
# 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
master:
url: jdbc:mysql://101.126.150.164:3307/sts?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: script
password: changfA123$
slave:
enabled: false
initialSize: 10
minIdle: 20
maxActive: 50
maxWait: 60000
connectTimeout: 30000
socketTimeout: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
maxEvictableIdleTimeMillis: 900000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: false
statViewServlet:
enabled: false
filter:
stat:
enabled: true
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
# redis 配置
redis:
enabled: false
host: 101.126.150.164
port: 6379
database: 5
password: script
timeout: 10s
lettuce:
pool:
min-idle: 5
max-idle: 20
max-active: 50
max-wait: -1ms
# 日志配置
logging:
level:
com.ruoyi: warn
org.springframework: warn
# Swagger配置
swagger:
enabled: false
pathMapping: /prod-api
# 防盗链配置
referer:
enabled: true
allowed-domains: 101.126.150.164,www.yourdomain.com
# 文件路径
ruoyi:
profile: F:/project/国际大科学计划网站/international-science-program-website/uploadPath
addressEnabled: true
# 测试环境配置
server:
port: 8081
# Spring配置
spring:
# 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
master:
url: jdbc:mysql://172.28.135.68:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
slave:
enabled: false
initialSize: 5
minIdle: 10
maxActive: 20
maxWait: 60000
connectTimeout: 30000
socketTimeout: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
maxEvictableIdleTimeMillis: 900000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
allow:
url-pattern: /druid/*
login-username: ruoyi
login-password: 123456
filter:
stat:
enabled: true
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
# redis 配置
redis:
enabled: true
host: 172.28.135.68
port: 6379
database: 0
password:
timeout: 10s
lettuce:
pool:
min-idle: 0
max-idle: 8
max-active: 8
max-wait: -1ms
# 日志配置
logging:
level:
com.ruoyi: info
org.springframework: warn
# Swagger配置
swagger:
enabled: true
pathMapping: /test-api
# 防盗链配置
referer:
enabled: true
allowed-domains: 172.28.135.68,101.126.159.207
# 文件路径
ruoyi:
profile: F:/ruoyi/uploadPath
addressEnabled: true
......@@ -2,7 +2,6 @@ package com.ruoyi.common.utils.file;
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;
......@@ -103,15 +102,26 @@ public class FileUploadUtils
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
return upload(baseDir, file, allowedExtension, false);
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);
String fileName = extractFilename(file);
File desc = getAbsoluteFile(baseDir, fileName);
file.transferTo(desc);
return getPathFileName(baseDir, fileName);
}
/**
* 文件上传
* 文件上传(使用UUID命名)
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param useCustomNaming 系统自定义文件名
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
......@@ -119,7 +129,7 @@ public class FileUploadUtils
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension, boolean useCustomNaming)
public static final String uploadWithUuid(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
......@@ -131,11 +141,9 @@ public class FileUploadUtils
assertAllowed(file, allowedExtension);
String fileName = useCustomNaming ? uuidFilename(file) : extractFilename(file);
String fileName = uuidFilename(file);
// 确保目录结构存在
File desc = getAbsoluteFile(baseDir, fileName);
// 使用 File 对象直接传输,避免路径格式问题
file.transferTo(desc);
return getPathFileName(baseDir, fileName);
}
......@@ -158,19 +166,13 @@ public class FileUploadUtils
public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
// 确保使用正确的路径分隔符
String filePath = uploadDir.replace("/", File.separator) + File.separator + fileName.replace("/", File.separator);
File desc = new File(filePath);
File desc = new File(uploadDir + File.separator + fileName);
// 确保父目录存在
File parentDir = desc.getParentFile();
if (!parentDir.exists())
if (!desc.exists())
{
// 确保创建所有必要的父目录
boolean created = parentDir.mkdirs();
if (!created)
if (!desc.getParentFile().exists())
{
throw new IOException("无法创建目录: " + parentDir.getAbsolutePath());
desc.getParentFile().mkdirs();
}
}
return desc;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment