Merge branch 'refs/heads/zt-test' into test
This commit is contained in:
@@ -6,6 +6,7 @@ import cn.hutool.http.HttpUtil;
|
||||
import com.zt.plat.framework.common.util.spring.SpringUtils;
|
||||
import com.zt.plat.module.infra.framework.file.core.client.AbstractFileClient;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
|
||||
@@ -22,6 +23,7 @@ import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignReques
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 基于 S3 协议的文件客户端,实现 MinIO、阿里云、腾讯云、七牛云、华为云等云服务
|
||||
@@ -32,6 +34,15 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
|
||||
|
||||
private static final Duration DEFAULT_PRESIGNED_EXPIRATION = Duration.ofHours(24);
|
||||
private static final String PRESIGN_EXPIRE_SECONDS_PROPERTY = "zt.file.download-expire-seconds";
|
||||
/**
|
||||
* Redis 缓存 key 前缀:文件预签名 URL
|
||||
*/
|
||||
private static final String CACHE_KEY_PREFIX = "file:presigned:url:";
|
||||
/**
|
||||
* Redis 缓存时间:50 分钟
|
||||
*/
|
||||
private static final long CACHE_EXPIRE_MINUTES = 50L;
|
||||
|
||||
/**
|
||||
* 生成临时下载地址(预签名下载 URL)
|
||||
* @param path 文件路径
|
||||
@@ -45,6 +56,17 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
// 1. 尝试从 Redis 缓存中获取
|
||||
String cacheKey = CACHE_KEY_PREFIX + path;
|
||||
RedisTemplate<String, Object> redis = getRedisTemplate();
|
||||
if (redis != null) {
|
||||
Object cachedUrl = redis.opsForValue().get(cacheKey);
|
||||
if (cachedUrl instanceof String) {
|
||||
return (String) cachedUrl;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 缓存未命中,调用 S3 生成预签名 URL
|
||||
// 使用 S3 官方支持的 responseCacheControl 参数,强制浏览器和代理不缓存
|
||||
GetObjectRequest.Builder getObjectRequestBuilder = GetObjectRequest.builder()
|
||||
.bucket(config.getBucket())
|
||||
@@ -54,12 +76,37 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
|
||||
.signatureDuration(realExpiration)
|
||||
.getObjectRequest(getObjectRequestBuilder.build())
|
||||
.build();
|
||||
return presigner.presignGetObject(getObjectPresignRequest).url().toString();
|
||||
String presignedUrl = presigner.presignGetObject(getObjectPresignRequest).url().toString();
|
||||
|
||||
// 3. 将生成的 URL 存入 Redis 缓存
|
||||
if (redis != null && presignedUrl != null && !presignedUrl.isEmpty()) {
|
||||
redis.opsForValue().set(cacheKey, presignedUrl, CACHE_EXPIRE_MINUTES, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
return presignedUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 RedisTemplate 实例(延迟加载,避免初始化时循环依赖)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private RedisTemplate<String, Object> getRedisTemplate() {
|
||||
if (redisTemplate == null) {
|
||||
try {
|
||||
redisTemplate = SpringUtils.getBean("redisTemplate", RedisTemplate.class);
|
||||
} catch (Exception e) {
|
||||
// Redis 不可用时,不影响正常功能,只是不使用缓存
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
private S3Client client;
|
||||
private S3Presigner presigner;
|
||||
|
||||
private RedisTemplate<String,Object> redisTemplate;
|
||||
|
||||
public S3FileClient(Long id, S3FileClientConfig config) {
|
||||
super(id, config);
|
||||
}
|
||||
@@ -115,6 +162,13 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
|
||||
.key(path)
|
||||
.build();
|
||||
client.deleteObject(deleteRequest);
|
||||
|
||||
// 删除文件后,清除对应的缓存
|
||||
String cacheKey = CACHE_KEY_PREFIX + path;
|
||||
RedisTemplate<String, Object> redis = getRedisTemplate();
|
||||
if (redis != null) {
|
||||
redis.delete(cacheKey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user