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 ...@@ -128,7 +128,7 @@ public class SysProfileController extends BaseController
if (!file.isEmpty()) if (!file.isEmpty())
{ {
LoginUser loginUser = getLoginUser(); 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)) if (userService.updateUserAvatar(loginUser.getUserId(), avatar))
{ {
String oldAvatar = loginUser.getUser().getAvatar(); 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; ...@@ -2,7 +2,6 @@ package com.ruoyi.common.utils.file;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects; import java.util.Objects;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
...@@ -103,15 +102,26 @@ public class FileUploadUtils ...@@ -103,15 +102,26 @@ public class FileUploadUtils
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException 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 baseDir 相对应用的基目录
* @param file 上传的文件 * @param file 上传的文件
* @param useCustomNaming 系统自定义文件名
* @param allowedExtension 上传文件类型 * @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名 * @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小 * @throws FileSizeLimitExceededException 如果超出最大大小
...@@ -119,7 +129,7 @@ public class FileUploadUtils ...@@ -119,7 +129,7 @@ public class FileUploadUtils
* @throws IOException 比如读写文件出错时 * @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常 * @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, throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException InvalidExtensionException
{ {
...@@ -131,11 +141,9 @@ public class FileUploadUtils ...@@ -131,11 +141,9 @@ public class FileUploadUtils
assertAllowed(file, allowedExtension); assertAllowed(file, allowedExtension);
String fileName = useCustomNaming ? uuidFilename(file) : extractFilename(file); String fileName = uuidFilename(file);
// 确保目录结构存在
File desc = getAbsoluteFile(baseDir, fileName); File desc = getAbsoluteFile(baseDir, fileName);
// 使用 File 对象直接传输,避免路径格式问题
file.transferTo(desc); file.transferTo(desc);
return getPathFileName(baseDir, fileName); return getPathFileName(baseDir, fileName);
} }
...@@ -158,19 +166,13 @@ public class FileUploadUtils ...@@ -158,19 +166,13 @@ public class FileUploadUtils
public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{ {
// 确保使用正确的路径分隔符 File desc = new File(uploadDir + File.separator + fileName);
String filePath = uploadDir.replace("/", File.separator) + File.separator + fileName.replace("/", File.separator);
File desc = new File(filePath);
// 确保父目录存在 if (!desc.exists())
File parentDir = desc.getParentFile();
if (!parentDir.exists())
{ {
// 确保创建所有必要的父目录 if (!desc.getParentFile().exists())
boolean created = parentDir.mkdirs();
if (!created)
{ {
throw new IOException("无法创建目录: " + parentDir.getAbsolutePath()); desc.getParentFile().mkdirs();
} }
} }
return desc; 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