🐛 修复 MinIO 预签名走外网 HTTPS,并过滤无效应收应付变更记录
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -95,7 +95,13 @@ public class FileConfig {
|
||||
FileStorageProperties.StoreProperties mergedProperties = new FileStorageProperties.StoreProperties();
|
||||
String fileStoragePrefix = "file.storage." + prefix;
|
||||
mergedProperties.setEndpoint(firstNotBlank(properties.getEndpoint(), environment.getProperty(fileStoragePrefix + ".endpoint"), environment.getProperty(prefix + ".endpoint")));
|
||||
mergedProperties.setTransformEndpoint(firstNotBlank(properties.getTransformEndpoint(), environment.getProperty(fileStoragePrefix + ".transform-endpoint"), environment.getProperty(prefix + ".transform-endpoint")));
|
||||
mergedProperties.setTransformEndpoint(firstNotBlank(
|
||||
properties.getTransformEndpoint(),
|
||||
environment.getProperty(fileStoragePrefix + ".transform-endpoint"),
|
||||
environment.getProperty(prefix + ".transform-endpoint"),
|
||||
// 兼容 blade-resource / oss 配置,避免仅改对象存储外网地址时分片上传仍走内网 HTTP
|
||||
environment.getProperty("oss.transform-endpoint")
|
||||
));
|
||||
mergedProperties.setAccessKeyId(firstNotBlank(properties.getAccessKeyId(), environment.getProperty(fileStoragePrefix + ".access-key-id"), environment.getProperty(fileStoragePrefix + ".access-key"), environment.getProperty(prefix + ".access-key-id"), environment.getProperty(prefix + ".access-key")));
|
||||
mergedProperties.setAccessKeySecret(firstNotBlank(properties.getAccessKeySecret(), environment.getProperty(fileStoragePrefix + ".access-key-secret"), environment.getProperty(fileStoragePrefix + ".secret-key"), environment.getProperty(prefix + ".access-key-secret"), environment.getProperty(prefix + ".secret-key")));
|
||||
mergedProperties.setBucketName(firstNotBlank(properties.getBucketName(), environment.getProperty(fileStoragePrefix + ".bucket-name"), environment.getProperty(prefix + ".bucket-name")));
|
||||
|
||||
+84
-6
@@ -25,11 +25,11 @@
|
||||
*/
|
||||
package org.springblade.file.service.impl;
|
||||
|
||||
import io.minio.ComposeObjectArgs;
|
||||
import io.minio.ComposeSource;
|
||||
import io.minio.GetObjectArgs;
|
||||
import io.minio.GetPresignedObjectUrlArgs;
|
||||
import io.minio.MinioClient;
|
||||
import io.minio.ComposeObjectArgs;
|
||||
import io.minio.ComposeSource;
|
||||
import io.minio.PutObjectArgs;
|
||||
import io.minio.RemoveObjectArgs;
|
||||
import io.minio.UploadObjectArgs;
|
||||
@@ -42,6 +42,7 @@ import org.springblade.file.config.FileStorageProperties;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
@@ -64,6 +65,7 @@ public class MinioFileServiceImpl extends AbstractFileService {
|
||||
|
||||
private final FileStorageProperties.StoreProperties properties;
|
||||
private final MinioClient minioClient;
|
||||
private volatile MinioClient transformPresignClient;
|
||||
|
||||
@Override
|
||||
public String initiateMultipartUpload(String objectKey) {
|
||||
@@ -73,9 +75,13 @@ public class MinioFileServiceImpl extends AbstractFileService {
|
||||
@Override
|
||||
public String getUploadPartUrl(String objectKey, String uploadId, Integer partNumber, Long expires) {
|
||||
try {
|
||||
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
|
||||
.method(Method.PUT).bucket(properties.getBucketName()).object(partObjectKey(objectKey, uploadId, partNumber))
|
||||
.expiry(Math.toIntExact(resolveExpires(expires))).build());
|
||||
String presignedUrl = resolvePresignClient().getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
|
||||
.method(Method.PUT)
|
||||
.bucket(properties.getBucketName())
|
||||
.object(partObjectKey(objectKey, uploadId, partNumber))
|
||||
.expiry(Math.toIntExact(resolveExpires(expires)))
|
||||
.build());
|
||||
return applyTransformPathPrefix(presignedUrl);
|
||||
} catch (Exception exception) {
|
||||
log.error("MinIO获取分片上传链接异常 objectKey:{}", objectKey, exception);
|
||||
throw new ServiceException("获取分片上传链接异常");
|
||||
@@ -143,12 +149,13 @@ public class MinioFileServiceImpl extends AbstractFileService {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
|
||||
String presignedUrl = resolvePresignClient().getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
|
||||
.method(Method.GET)
|
||||
.bucket(properties.getBucketName())
|
||||
.object(resolveObjectKey(objectKey))
|
||||
.expiry(Math.toIntExact(resolveExpires(expires)))
|
||||
.build());
|
||||
return applyTransformPathPrefix(presignedUrl);
|
||||
} catch (Exception exception) {
|
||||
log.error("MinIO获取文件链接异常 objectKey:{}", objectKey, exception);
|
||||
throw new ServiceException("MinIO获取文件链接异常");
|
||||
@@ -170,6 +177,77 @@ public class MinioFileServiceImpl extends AbstractFileService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 浏览器侧预签名优先使用外网地址,避免 HTTPS 页面访问 HTTP MinIO 被 Mixed Content 拦截。
|
||||
* MinIO SDK 不允许 endpoint 带 path,因此外网地址中的 /oss 等前缀在签名后单独拼回。
|
||||
*/
|
||||
private MinioClient resolvePresignClient() {
|
||||
String transformEndpoint = properties.getTransformEndpoint();
|
||||
if (StringUtil.isBlank(transformEndpoint)) {
|
||||
return minioClient;
|
||||
}
|
||||
MinioClient cachedClient = transformPresignClient;
|
||||
if (cachedClient != null) {
|
||||
return cachedClient;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (transformPresignClient == null) {
|
||||
transformPresignClient = MinioClient.builder()
|
||||
.endpoint(resolveTransformOrigin(transformEndpoint))
|
||||
.credentials(properties.getAccessKeyId(), properties.getAccessKeySecret())
|
||||
.build();
|
||||
}
|
||||
return transformPresignClient;
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveTransformOrigin(String transformEndpoint) {
|
||||
URI transformUri = URI.create(transformEndpoint.trim());
|
||||
if (StringUtil.isBlank(transformUri.getScheme()) || StringUtil.isBlank(transformUri.getHost())) {
|
||||
throw new ServiceException("MinIO外网地址配置不正确");
|
||||
}
|
||||
StringBuilder origin = new StringBuilder();
|
||||
origin.append(transformUri.getScheme()).append("://").append(transformUri.getHost());
|
||||
if (transformUri.getPort() > 0) {
|
||||
origin.append(':').append(transformUri.getPort());
|
||||
}
|
||||
return origin.toString();
|
||||
}
|
||||
|
||||
private String applyTransformPathPrefix(String presignedUrl) {
|
||||
String transformEndpoint = properties.getTransformEndpoint();
|
||||
if (StringUtil.isBlank(transformEndpoint) || StringUtil.isBlank(presignedUrl)) {
|
||||
return presignedUrl;
|
||||
}
|
||||
String pathPrefix = normalizePathPrefix(URI.create(transformEndpoint.trim()).getPath());
|
||||
if (StringUtil.isBlank(pathPrefix)) {
|
||||
return presignedUrl;
|
||||
}
|
||||
URI url = URI.create(presignedUrl);
|
||||
String path = url.getRawPath() == null ? "" : url.getRawPath();
|
||||
if (path.equals(pathPrefix) || path.startsWith(pathPrefix + "/")) {
|
||||
return presignedUrl;
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append(url.getScheme()).append("://").append(url.getHost());
|
||||
if (url.getPort() > 0) {
|
||||
result.append(':').append(url.getPort());
|
||||
}
|
||||
result.append(pathPrefix).append(path);
|
||||
if (StringUtil.isNotBlank(url.getRawQuery())) {
|
||||
result.append('?').append(url.getRawQuery());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private String normalizePathPrefix(String path) {
|
||||
if (StringUtil.isBlank(path) || "/".equals(path)) {
|
||||
return "";
|
||||
}
|
||||
String normalized = path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
|
||||
return normalized.startsWith("/") ? normalized : "/" + normalized;
|
||||
}
|
||||
|
||||
private String resolveObjectKey(String objectKey) {
|
||||
if (StringUtil.isBlank(properties.getRootDirectory())) {
|
||||
return objectKey;
|
||||
|
||||
Reference in New Issue
Block a user