feat(material): remove video cover extraction and simplify upload API

- Remove extractVideoCoverOptional function and related video cover processing
- Update MaterialService.uploadFile method signature to remove coverBase64 parameter
- Simplify uploadAndIdentifyVideo function by removing cover generation logic
- Remove loading indicator from VideoSelector component during video preview
- Add presignGetUrlWithProcess method to FileClient interface for processed file URLs
- Add logging support to S3FileClient implementation
This commit is contained in:
2026-03-04 22:37:31 +08:00
parent 07579e27e9
commit 27d1c53b49
23 changed files with 576 additions and 361 deletions

View File

@@ -52,6 +52,19 @@ public interface FileApi {
String presignGetUrl(@NotEmpty(message = "URL 不能为空") String url,
Integer expirationSeconds);
/**
* 生成文件预签名地址(带 OSS 处理参数),用于读取
* 用于阿里云 OSS 视频截帧等图片处理场景
*
* @param url 完整的文件访问地址
* @param expirationSeconds 访问有效期,单位秒
* @param processParam OSS 处理参数,如 "video/snapshot,t_1000,f_jpg,w_300"
* @return 文件预签名地址
*/
String presignGetUrlWithProcess(@NotEmpty(message = "URL 不能为空") String url,
Integer expirationSeconds,
String processParam);
/**
* 获取主文件配置的自定义域名CDN域名
*

View File

@@ -34,6 +34,11 @@ public class FileApiImpl implements FileApi {
return fileService.presignGetUrl(url, expirationSeconds);
}
@Override
public String presignGetUrlWithProcess(String url, Integer expirationSeconds, String processParam) {
return fileService.presignGetUrlWithProcess(url, expirationSeconds, processParam);
}
@Override
public String getMasterFileDomain() {
FileClient client = fileConfigService.getMasterFileClient();

View File

@@ -74,6 +74,24 @@ public interface FileClient {
throw new UnsupportedOperationException("不支持的操作");
}
/**
* 生成文件预签名地址(带 OSS 处理参数),用于读取
*
* <p>用于阿里云 OSS 视频截帧、图片处理等场景。
* 将处理参数包含在签名中,避免私有桶访问时返回 403。
*
* <p><b>注意</b>:此方法仅阿里云 OSS 支持,其他云厂商会忽略 processParam 参数。
*
* @param url 完整的文件访问地址
* @param expirationSeconds 访问有效期,单位秒
* @param processParam OSS 处理参数,如 "video/snapshot,t_1000,f_jpg,w_300"
* 参考https://help.aliyun.com/document_detail/99285.html
* @return 文件预签名地址(处理参数已包含在签名中)
*/
default String presignGetUrlWithProcess(String url, Integer expirationSeconds, String processParam) {
throw new UnsupportedOperationException("不支持的操作");
}
/**
* 获取文件配置
*

View File

@@ -34,11 +34,14 @@ import java.util.Date;
import org.springframework.web.util.UriUtils;
import lombok.extern.slf4j.Slf4j;
/**
* 基于 S3 协议的文件客户端,实现 MinIO、阿里云、腾讯云、七牛云、华为云等云服务
*
* @author 芋道源码
*/
@Slf4j
public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
private static final Duration EXPIRATION_DEFAULT = Duration.ofHours(24);
@@ -198,24 +201,44 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
@Override
public String presignGetUrl(String url, Integer expirationSeconds) {
return presignGetUrlWithProcess(url, expirationSeconds, null);
}
@Override
public String presignGetUrlWithProcess(String url, Integer expirationSeconds, String processParam) {
// 1. 将 url 转换为 path支持 CDN 域名和 OSS 原始域名)
String path = extractPathFromUrl(url);
String decodedPath = URLUtil.decode(path, StandardCharsets.UTF_8);
// 2. 公开访问:无需签名
// 2. 公开访问:无需签名,直接拼接参数
if (!BooleanUtil.isFalse(config.getEnablePublicAccess())) {
String encodedPath = UriUtils.encodePath(decodedPath, StandardCharsets.UTF_8);
return config.getDomain() + "/" + encodedPath;
String resultUrl = config.getDomain() + "/" + encodedPath;
if (StrUtil.isNotBlank(processParam)) {
resultUrl = resultUrl + "?x-oss-process=" + processParam;
}
return resultUrl;
}
// 3. 私有访问:生成预签名 URL
// 3. 私有访问:生成预签名 URL(需要将处理参数包含在签名中)
int expiration = expirationSeconds != null ? expirationSeconds : (int) EXPIRATION_DEFAULT.getSeconds();
String signedUrl;
if (isAliyun) {
Date expirationDate = new Date(System.currentTimeMillis() + expiration * 1000L);
signedUrl = aliyunOssClient.generatePresignedUrl(config.getBucket(), decodedPath, expirationDate).toString();
com.aliyun.oss.model.GeneratePresignedUrlRequest request =
new com.aliyun.oss.model.GeneratePresignedUrlRequest(config.getBucket(), decodedPath, HttpMethod.GET);
request.setExpiration(expirationDate);
// 关键:将 x-oss-process 参数包含在签名中
if (StrUtil.isNotBlank(processParam)) {
request.addQueryParameter("x-oss-process", processParam);
}
signedUrl = aliyunOssClient.generatePresignedUrl(request).toString();
} else {
// 非阿里云不支持 OSS 处理参数,直接返回普通预签名 URL
if (StrUtil.isNotBlank(processParam)) {
log.warn("[presignGetUrlWithProcess] 非阿里云 OSS 不支持处理参数已忽略。processParam={}", processParam);
}
Duration duration = Duration.ofSeconds(expiration);
signedUrl = s3Presigner.presignGetObject(GetObjectPresignRequest.builder()
.signatureDuration(duration)

View File

@@ -54,6 +54,17 @@ public interface FileService {
*/
String presignGetUrl(String url, Integer expirationSeconds);
/**
* 生成文件预签名地址(带 OSS 处理参数),用于读取
* 用于阿里云 OSS 视频截帧等图片处理场景
*
* @param url 完整的文件访问地址
* @param expirationSeconds 访问有效期,单位秒
* @param processParam OSS 处理参数,如 "video/snapshot,t_1000,f_jpg,w_300"
* @return 文件预签名地址
*/
String presignGetUrlWithProcess(String url, Integer expirationSeconds, String processParam);
/**
* 创建文件
*

View File

@@ -146,6 +146,12 @@ public class FileServiceImpl implements FileService {
return fileClient.presignGetUrl(url, expirationSeconds);
}
@Override
public String presignGetUrlWithProcess(String url, Integer expirationSeconds, String processParam) {
FileClient fileClient = fileConfigService.getMasterFileClient();
return fileClient.presignGetUrlWithProcess(url, expirationSeconds, processParam);
}
@Override
public Long createFile(FileCreateReqVO createReqVO) {
createReqVO.setUrl(HttpUtils.removeUrlQuery(createReqVO.getUrl())); // 目的移除私有桶情况下URL 的签名参数