处理下载为公共模块

This commit is contained in:
super
2026-06-12 13:40:29 +08:00
parent 17236265c6
commit 8672668c33
13 changed files with 62 additions and 37 deletions
@@ -10,9 +10,8 @@ import org.springframework.stereotype.Service;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;
@@ -23,8 +22,8 @@ public class OssStorageService {
private final OssProperties ossProperties;
/**
* 上传结果文件到 OSS,返回 objectKey(非预签名 URL
* 调用方应存储 objectKey,下载时通过 generateFreshDownloadUrl 按需生成链接
* 上传结果文件到 OSS,返回 objectKey。
* 调用方应存储 objectKey,下载时通过 generateFreshDownloadUrl 生成公开直链
*/
public String uploadResultFile(File file, String moduleType) {
String objectKey = String.format("result/%s/%s/%s", moduleType.toLowerCase(), UUID.randomUUID(), file.getName());
@@ -42,9 +41,7 @@ public class OssStorageService {
OSS ossClient = buildClient();
try {
ossClient.putObject(ossProperties.getBucket(), objectKey, file);
Date expiration = new Date(System.currentTimeMillis() + 3600_000L);
URL url = ossClient.generatePresignedUrl(ossProperties.getBucket(), objectKey, expiration);
return new UploadedResult(objectKey, url.toString());
return new UploadedResult(objectKey, getPublicUrl(objectKey));
} finally {
ossClient.shutdown();
}
@@ -113,32 +110,32 @@ public class OssStorageService {
}
/**
* 根据 objectKey 生成预签名下载 URL1小时有效)
* 根据 objectKey 生成公开直链下载 URL。
*/
public String generateDownloadUrl(String objectKey) {
OSS ossClient = buildClient();
try {
Date expiration = new Date(System.currentTimeMillis() + 3600_000L);
URL url = ossClient.generatePresignedUrl(ossProperties.getBucket(), objectKey, expiration);
return url.toString();
} finally {
ossClient.shutdown();
}
return getPublicUrl(objectKey);
}
/**
* 获取公开(无签名)URL,格式:https://{bucket}.{endpoint}/{objectKey}
*/
public String getPublicUrl(String objectKey) {
if (objectKey == null || objectKey.isBlank()) {
public String getPublicUrl(String value) {
if (value == null || value.isBlank()) {
return null;
}
return String.format("https://%s.%s/%s", ossProperties.getBucket(), ossProperties.getEndpoint(), objectKey);
String objectKey = resolveObjectKey(value);
String normalizedKey = objectKey.startsWith("/") ? objectKey.substring(1) : objectKey;
String host = String.format("%s.%s", ossProperties.getBucket(), ossProperties.getEndpoint());
try {
return new URI("https", host, "/" + normalizedKey, null).toASCIIString();
} catch (Exception ignored) {
return String.format("https://%s/%s", host, normalizedKey);
}
}
/**
* 从存储值中解析出 objectKey,兼容两种格式:
* - 旧格式:完整预签名 URLhttps://bucket.endpoint/objectKey?Expires=...
* - 旧格式:完整 URLhttps://bucket.endpoint/objectKey?Expires=...
* - 新格式:直接是 objectKey(如 result/dedupe/uuid/file.xlsx
*/
public String resolveObjectKey(String value) {
@@ -151,13 +148,21 @@ public class OssStorageService {
return path.startsWith("/") ? path.substring(1) : path;
}
} catch (Exception ignored) {
int schemeEnd = value.indexOf("://");
int pathStart = schemeEnd < 0 ? -1 : value.indexOf('/', schemeEnd + 3);
if (pathStart >= 0 && pathStart + 1 < value.length()) {
String path = value.substring(pathStart + 1);
int queryStart = path.indexOf('?');
String objectKey = queryStart >= 0 ? path.substring(0, queryStart) : path;
return URLDecoder.decode(objectKey, StandardCharsets.UTF_8);
}
}
return value;
}
/**
* 根据存储值(objectKey 或旧格式预签名 URL)生成新鲜的预签名下载 URL。
* 供各模块 listHistory 使用,每次按需生成,避免旧 URL 1小时后过期。
* 根据存储值(objectKey 或旧格式完整 URL)生成公开直链下载 URL。
* 供各模块 listHistory 和下载接口使用,避免签名过期。
*/
public String generateFreshDownloadUrl(String value) {
if (value == null || value.isBlank()) {