feat(file-upload): 集成新疆OSS文件上传功能并优化设备删除逻辑

- 实现新疆油田平台OSS文件上传工具类XjOssUtil,支持OAuth2鉴权和文件操作
- 在MyUploadUtil中集成OSS上传逻辑,通过oss_flag配置动态选择上传方式
- 为.tar和.apk文件强制使用MyUploadUtil上传,其他文件根据oss_flag配置决定上传方式
- 在手表设备删除接口中增加绑定用户检查,已绑定用户的手表不允许删除
- 添加GlobalManager依赖注入以支持动态配置读取
- 实现文件上传流程的日志记录和错误处理机制
This commit is contained in:
2026-04-21 17:22:09 +08:00
parent 44b0f6ca2b
commit 1988e031e5
7 changed files with 927 additions and 166 deletions
@@ -1,10 +1,12 @@
package org.jeecg.modules.system.controller;
import cn.hutool.core.util.StrUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.MyUploadUtil;
import org.jeecg.common.util.XjOssUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.oss.service.IOssFileService;
import org.jeecg.modules.system.bean.request.UploadFilsDTO;
@@ -15,6 +17,11 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -89,6 +96,9 @@ public class SysUploadController {
} catch (Exception e) {
return Result.error(e.getMessage());
}
if (StrUtil.isBlank(fileUrl)){
return Result.error("上传失败,请检查配置信息是否正确!");
}
Map map = new HashMap();
map.put("url", fileUrl);
return Result.OK(map);
@@ -115,4 +125,94 @@ public class SysUploadController {
return Result.OK(urlList);
}
@Operation(summary = "IOSP文件下载", description = "根据 fileKey 下载文件,如 sys/upload/down/808fec...@aa.png")
@RequestMapping(value = "/down/**", method = RequestMethod.GET)
public void fileDown(HttpServletRequest request, HttpServletResponse response) throws Exception {
String fileKey = extractPathParam(request, "/down/");
if (isIllegalFileKey(fileKey)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "fileKey 格式非法");
return;
}
try (InputStream in = XjOssUtil.down(fileKey)) {
if (in == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, "文件不存在或下载失败");
return;
}
// 从 fileKey 中取文件名(@ 后面的部分)
String fileName = fileKey.contains("@") ? fileKey.substring(fileKey.indexOf("@") + 1) : fileKey;
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
try (OutputStream out = response.getOutputStream()) {
byte[] buf = new byte[4096];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
out.flush();
}
} catch (Exception e) {
log.error("[SysUploadController] IOSP文件下载失败, fileKey={}", fileKey, e);
}
}
@Operation(summary = "IOSP文件预览", description = "根据 fileKey 获取预览地址,如 sys/upload/show/808fec...@aa.png")
@RequestMapping(value = "/show/**", method = RequestMethod.GET)
public void fileShow(HttpServletRequest request, HttpServletResponse response) throws Exception {
String fileKey = extractPathParam(request, "/show/");
if (isIllegalFileKey(fileKey)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "fileKey 格式非法");
return;
}
try {
String url = XjOssUtil.show(fileKey);
if (url == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, "文件不存在或获取预览地址失败");
return;
}
// 重定向到真实预览地址
response.sendRedirect(url);
} catch (Exception e) {
log.error("[SysUploadController] IOSP文件预览失败, fileKey={}", fileKey, e);
}
}
/**
* 从请求路径中提取 fileKey
* <p>截取 marker 之后的路径部分,并做 URL 解码</p>
*/
private String extractPathParam(HttpServletRequest request, String marker) {
String uri = request.getRequestURI();
int idx = uri.indexOf(marker);
if (idx < 0) {
return "";
}
String raw = uri.substring(idx + marker.length());
try {
return java.net.URLDecoder.decode(raw, "UTF-8");
} catch (Exception e) {
return raw;
}
}
/**
* 校验 fileKey 是否存在路径穿透风险
* <p>
* 拦截 ../、..\ 及其 URL 编码变体(%2e%2e%2f 等),防止跳出授权目录
* </p>
*/
private boolean isIllegalFileKey(String fileKey) {
if (oConvertUtils.isEmpty(fileKey)) {
return true;
}
// 先做 URL 解码,防止编码绕过
String decoded;
try {
decoded = java.net.URLDecoder.decode(fileKey, "UTF-8");
} catch (Exception e) {
return true;
}
return decoded.contains("../") || decoded.contains("..\\")
|| decoded.startsWith("..") || decoded.contains("/..");
}
}