fix: uploadOnLineResource支持任何网络资源URL,并修复登录状态过期问题

This commit is contained in:
wangzhiwei 2026-01-06 10:45:05 +08:00
parent 6a8583d634
commit 94c71b10e4
7 changed files with 187 additions and 21 deletions

View File

@ -97,17 +97,25 @@ public class LoginHelper {
* @return 登录用户信息未登录时返回null
*/
public static LoginUser getLoginUserSafely() {
if (!StpUtil.isLogin()) {
try {
if (!StpUtil.isLogin()) {
return null;
}
LoginUser loginUser = (LoginUser)SaHolder.getStorage().get(CacheConstants.LOGIN_USER_KEY);
if (null != loginUser) {
return loginUser;
}
SaSession tokenSession = StpUtil.getTokenSession();
loginUser = (LoginUser)tokenSession.get(CacheConstants.LOGIN_USER_KEY);
SaHolder.getStorage().set(CacheConstants.LOGIN_USER_KEY, loginUser);
return loginUser;
} catch (NotLoginException e) {
// 捕获未登录异常返回null
return null;
} catch (Exception e) {
// 捕获其他异常返回null
return null;
}
LoginUser loginUser = (LoginUser)SaHolder.getStorage().get(CacheConstants.LOGIN_USER_KEY);
if (null != loginUser) {
return loginUser;
}
SaSession tokenSession = StpUtil.getTokenSession();
loginUser = (LoginUser)tokenSession.get(CacheConstants.LOGIN_USER_KEY);
SaHolder.getStorage().set(CacheConstants.LOGIN_USER_KEY, loginUser);
return loginUser;
}
/**

View File

@ -5,12 +5,13 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.EscapeUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.recorder.FileRecorder;
import org.dromara.x.file.storage.core.upload.FilePartInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.continew.admin.common.model.dto.LoginUser;
import top.continew.admin.common.util.helper.LoginHelper;
import top.continew.admin.system.enums.FileTypeEnum;
import top.continew.admin.system.mapper.FileMapper;
@ -31,12 +32,16 @@ import java.util.Optional;
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class FileRecorderImpl implements FileRecorder {
private final FileMapper fileMapper;
private final StorageMapper storageMapper;
private final UserService userService;
@Autowired
private FileMapper fileMapper;
@Autowired
private StorageMapper storageMapper;
@Autowired
private UserService userService;
@Override
public boolean save(FileInfo fileInfo) {
@ -53,16 +58,37 @@ public class FileRecorderImpl implements FileRecorder {
file.setThumbnailSize(fileInfo.getThSize());
StorageDO storage = (StorageDO)fileInfo.getAttr().get(ClassUtil.getClassName(StorageDO.class, false));
file.setStorageId(storage.getId());
if (LoginHelper.getLoginUserSafely() == null) {
UserDO user = userService.getById(StpUtil.getLoginIdAsLong());
file.setDeptId(user.getDeptId());
// 安全获取登录用户信息
Long userId = 0L; // 默认用户ID
Long deptId = 0L; // 默认部门ID
LoginUser loginUser = LoginHelper.getLoginUserSafely();
if (loginUser != null) {
userId = loginUser.getId();
deptId = loginUser.getDeptId();
} else {
file.setDeptId(LoginHelper.getLoginUserSafely().getDeptId());
// 尝试通过StpUtil获取登录ID同时捕获可能的异常
try {
// 检查是否登录
if (StpUtil.isLogin()) {
userId = StpUtil.getLoginIdAsLong();
// 获取用户部门信息
UserDO user = userService.getById(userId);
if (user != null) {
deptId = user.getDeptId();
}
}
} catch (Exception e) {
// 捕获所有异常使用默认值
log.debug("获取登录用户信息失败: {}", e.getMessage());
}
}
file.setCreateUser(StpUtil.getLoginIdAsLong());
file.setDeptId(deptId);
file.setCreateUser(userId);
file.setCreateTime(DateUtil.toLocalDateTime(fileInfo.getCreateTime()));
file.setUpdateUser(StpUtil.getLoginIdAsLong());
file.setUpdateUser(userId);
file.setUpdateTime(file.getCreateTime());
fileMapper.insert(file);
return true;

View File

@ -0,0 +1,15 @@
package top.continew.admin.system.model.req;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.io.Serializable;
@Data
public class uploadOnlineResourceReq implements Serializable {
private static final long serialVersionUID = 1L;
@NotEmpty(message = "文件URL不能为空")
private String url;
}

View File

@ -74,4 +74,6 @@ public interface FileService extends BaseService<FileResp, FileResp, FileQuery,
*/
PageResp<FileResp> getFilesPage(FileQuery query, PageQuery pageQuery);
FileInfo uploadOnLineResource(String url);
}

View File

@ -38,6 +38,10 @@ import top.continew.starter.extension.crud.model.query.PageQuery;
import top.continew.starter.extension.crud.model.resp.PageResp;
import top.continew.starter.extension.crud.service.impl.BaseServiceImpl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
@ -201,6 +205,108 @@ public class FileServiceImpl extends BaseServiceImpl<FileMapper, FileDO, FileRes
return PageResp.build(page);
}
@Override
public FileInfo uploadOnLineResource(String url) {
StorageDO storage = storageService.getDefaultStorage();
CheckUtils.throwIfNull(storage, "请先指定默认存储");
// 先检查URL是否有效
if (StrUtil.isBlank(url)) {
throw new IllegalArgumentException("URL不能为空");
}
// 使用通用HTTP客户端下载任何网络资源到字节数组
byte[] bytes;
try {
java.net.URL resourceUrl = new java.net.URL(url);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection)resourceUrl.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setReadTimeout(10000);
int responseCode = connection.getResponseCode();
if (responseCode != 200) {
throw new RuntimeException("下载资源失败HTTP状态码: " + responseCode + "URL: " + url);
}
try (java.io.InputStream inputStream = connection.getInputStream()) {
bytes = inputStream.readAllBytes();
}
connection.disconnect();
} catch (Exception e) {
throw new RuntimeException("下载资源时发生错误: " + e.getMessage(), e);
}
if (bytes == null || bytes.length == 0) {
throw new RuntimeException("下载的文件内容为空: " + url);
}
// 获取文件名和扩展名
String filename = URLUtil.decode(FileNameUtil.getName(url));
String ext = FileNameUtil.extName(filename);
String name = FileNameUtil.mainName(filename);
LocalDate today = LocalDate.now();
String path = today.getYear() + StringConstants.SLASH + today.getMonthValue() + StringConstants.SLASH + today
.getDayOfMonth() + StringConstants.SLASH;
// 创建临时文件
File tempFile = null;
try {
tempFile = File.createTempFile(name, "." + ext);
} catch (IOException e) {
throw new RuntimeException(e);
}
try (FileOutputStream fos = new FileOutputStream(tempFile)) {
fos.write(bytes);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
// 上传到指定存储
UploadPretreatment uploadPretreatment = fileStorageService.of(tempFile)
.setPlatform(storage.getCode())
.putAttr(ClassUtil.getClassName(StorageDO.class, false), storage)
.setPath(path);
// 图片文件生成缩略图
if (FileTypeEnum.IMAGE.getExtensions().contains(ext)) {
uploadPretreatment.thumbnail(img -> img.size(100, 100));
}
uploadPretreatment.setProgressMonitor(new ProgressListener() {
@Override
public void start() {
log.info("开始上传在线资源: {}", url);
}
@Override
public void progress(long progressSize, Long allSize) {
if (allSize != null) {
log.info("已上传 [{}],总大小 [{}],进度: [{}%]", progressSize, allSize, String
.format("%.2f", (double)progressSize / allSize * 100));
} else {
log.info("已上传 [{}]", progressSize);
}
}
@Override
public void finish() {
log.info("上传结束: {}", url);
}
});
// 处理本地存储文件 URL
FileInfo fileInfo = uploadPretreatment.upload();
String domain = StrUtil.appendIfMissing(storage.getDomain(), StringConstants.SLASH);
fileInfo.setUrl(URLUtil.normalize(domain + fileInfo.getPath() + fileInfo.getFilename()));
return fileInfo;
}
@Override
protected void fill(Object obj) {
super.fill(obj);

View File

@ -20,6 +20,7 @@ import top.continew.admin.system.model.query.DeptQuery;
import top.continew.admin.system.model.query.MenuQuery;
import top.continew.admin.system.model.query.OptionQuery;
import top.continew.admin.system.model.query.RoleQuery;
import top.continew.admin.system.model.req.uploadOnlineResourceReq;
import top.continew.admin.system.model.resp.DeptChildResp;
import top.continew.admin.system.model.resp.FileUploadResp;
import top.continew.admin.system.service.*;
@ -59,6 +60,13 @@ public class CommonController {
return FileUploadResp.builder().url(fileInfo.getUrl()).build();
}
@Operation(summary = "上传文件-将ai生成的网络资源转换成本地资源", description = "上传文件-将ai生成的网络资源转换成本地资源")
@PostMapping("/uploadOnLineResource")
public FileUploadResp upload(@RequestBody @Validated uploadOnlineResourceReq req) {
FileInfo fileInfo = fileService.uploadOnLineResource(req.getUrl());
return FileUploadResp.builder().url(fileInfo.getUrl()).build();
}
@Operation(summary = "查询部门树", description = "查询树结构的部门列表")
@GetMapping("/tree/dept")
public List<Tree<Long>> listDeptTree(DeptQuery query, SortQuery sortQuery) {

View File

@ -227,9 +227,10 @@ justauth:
--- ### Sa-Token 扩展配置
sa-token.extension:
# 安全配置:排除(放行)路径配置
# 安全获取登录用户信息如果未登录返回null
security.excludes:
# 白名单
- /common/uploadOnLineResource
- /consumptionHistory/add
- /taskRecordHistory/add
- /consumptionHistory/checkBalance