From 9c3c085032bddf6bb5e8b730067292e7f1520328 Mon Sep 17 00:00:00 2001
From: zhaowenyu <35589726@qq.com>
Date: Wed, 04 Feb 2026 14:54:56 +0800
Subject: [PATCH] 2026-02-04 优化minio上传
---
ard-admin/src/main/java/com/ard/web/controller/sample/media/MinioProxyUploadController.java | 38 +++++++++++++++++++++++++++-----------
1 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/ard-admin/src/main/java/com/ard/web/controller/sample/media/MinioProxyUploadController.java b/ard-admin/src/main/java/com/ard/web/controller/sample/media/MinioProxyUploadController.java
index 649e862..97a59b7 100644
--- a/ard-admin/src/main/java/com/ard/web/controller/sample/media/MinioProxyUploadController.java
+++ b/ard-admin/src/main/java/com/ard/web/controller/sample/media/MinioProxyUploadController.java
@@ -75,22 +75,38 @@
HttpServletRequest request
) {
log.info("接收参数bucketName:{}",bucketName);
- // ===================== 1. 解析原始路径:保留所有斜杠/末尾分隔符,完全对齐原生MinIO =====================
- String rawUri = request.getRequestURI();
- String requestUri = URLDecoder.decode(rawUri, StandardCharsets.UTF_8);
+ // ===================== 核心修复:安全路径解析,替换替代截取,杜绝索引错误 =====================
+ // String contextPath = request.getContextPath();
+ String rawUri = URLDecoder.decode(request.getRequestURI(), StandardCharsets.UTF_8);
+ // 剔除上下文路径,得到纯业务路径
+ String purePath = rawUri.substring("/minioTransfer".length());
String bucketPrefix = "/" + bucketName;
- // 提取原始ObjectKey,无任何修改
- String objectKey = requestUri.substring(bucketPrefix.length());
- log.info("中转MinIO PUT请求 | 桶名:{} | 原始对象路径:{} | 请求体大小:{}byte",
- bucketName, objectKey, rawRequestBody == null ? 0 : rawRequestBody.length);
+ log.info("中转MinIO 路径解析开始 | 原始URI:{} | 纯业务路径:{} | 桶前缀:{}", rawUri, purePath, bucketPrefix);
+
+ // 校验路径是否以桶前缀开头
+ if (!purePath.startsWith(bucketPrefix)) {
+ return buildNativeS3Error("InvalidRequest", "请求路径格式不匹配", rawUri, HttpStatus.BAD_REQUEST);
+ }
+
+ // 修复点:replace替换前缀,替代 substring 长度截取,彻底解决索引错位问题
+ String objectKey = purePath.replaceFirst("^" + bucketPrefix, "");
+ // 兜底处理空路径
+ if (objectKey.isEmpty()) {
+ objectKey = "/";
+ }
+
+ log.info("中转MinIO 路径解析成功 | 纯业务路径:{} | 桶名:{} | 最终对象路径:{}",
+ purePath, bucketName, objectKey);
+
+ // byte[] requestData = rawRequestBody == null ? new byte[0] : rawRequestBody;
try {
// ===================== 2. 复用原有逻辑:获取临时凭证 =====================
var credentials = ossService.getCredentials();
if (credentials == null || credentials.getAccessKeyId() == null || credentials.getSecurityToken() == null) {
log.error("临时凭证获取失败");
- return buildNativeS3Error("InvalidCredentials", "临时凭证无效", requestUri, HttpStatus.FORBIDDEN);
+ return buildNativeS3Error("InvalidCredentials", "临时凭证无效", rawUri, HttpStatus.FORBIDDEN);
}
// ===================== 3. 复用原有逻辑:构建MinIO客户端 =====================
@@ -106,7 +122,7 @@
// 校验桶存在性(兼容原生接口行为,桶不存在返回404)
boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (!bucketExists) {
- return buildNativeS3Error("NoSuchBucket", "指定存储桶不存在", requestUri, HttpStatus.NOT_FOUND);
+ return buildNativeS3Error("NoSuchBucket", "指定存储桶不存在", bucketName, HttpStatus.NOT_FOUND);
}
// ===================== 4. 透传请求:原样转发大疆原始数据到MinIO,无业务篡改 =====================
@@ -145,10 +161,10 @@
.body(nativeError);
} catch (MinioException e) {
log.error("MinIO客户端异常:{}", e.getMessage());
- return buildNativeS3Error("ClientError", e.getMessage(), requestUri, HttpStatus.INTERNAL_SERVER_ERROR);
+ return buildNativeS3Error("ClientError", e.getMessage(), rawUri, HttpStatus.INTERNAL_SERVER_ERROR);
} catch (Exception e) {
log.error("代理中转通用异常:{}", e.getMessage(), e);
- return buildNativeS3Error("InternalError", "服务器代理异常", requestUri, HttpStatus.INTERNAL_SERVER_ERROR);
+ return buildNativeS3Error("InternalError", "服务器代理异常", rawUri, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
--
Gitblit v1.9.3