feat(assets): add 2GB file size validation and OSS direct upload for large files
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Lint (pull_request) Has been cancelled

- Add MAX_FILE_SIZE (2GB) validation in handleUpload with friendly error message
- Route files >100MB through OSS presigned direct upload (uploadAssetDirect)
- Keep small file form upload (uploadAsset) for files <=100MB
- Update upload hint text to show '单文件不超过 2GB' limit
- Add directUploadMutation with proper loading state tracking

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Audit Bot
2026-06-29 22:13:08 +08:00
parent b98c83582b
commit b5e27a5e9e
+43 -10
View File
@@ -37,12 +37,18 @@ import {
getAssets,
deleteAsset,
uploadAsset,
uploadAssetDirect,
} from '@/api/assets';
import { getOrCreateDefaultProject } from '@/api/projects';
const { Title, Text } = Typography;
const { Dragger } = Upload;
/** 最大文件大小:2GB */
const MAX_FILE_SIZE = 2 * 1024 * 1024 * 1024; // 2147483648 bytes
/** 大文件阈值:100MB,超过此值走 OSS 直传通道 */
const LARGE_FILE_THRESHOLD = 100 * 1024 * 1024; // 104857600 bytes
/** 素材库类型图标 */
const KindIcon: React.FC<{ kind: string }> = ({ kind }) => {
switch (kind) {
@@ -99,7 +105,7 @@ const AssetLibrary: React.FC = () => {
onError: (err: any) => { if (!err?.__msgShown) message.error('创建失败') },
});
// 上传素材
// 上传素材(小文件表单上传)
const uploadMutation = useMutation({
mutationFn: uploadAsset,
onSuccess: () => {
@@ -110,6 +116,17 @@ const AssetLibrary: React.FC = () => {
onError: (err: any) => { if (!err?.__msgShown) message.error('上传失败') },
});
// 大文件直传(OSS 预签名)
const directUploadMutation = useMutation({
mutationFn: uploadAssetDirect,
onSuccess: () => {
message.success('上传成功');
queryClient.invalidateQueries({ queryKey: ['assets', activeLibrary] });
queryClient.invalidateQueries({ queryKey: ['asset-libraries'] });
},
onError: (err: any) => { if (!err?.__msgShown) message.error('上传失败') },
});
// 删除素材
const deleteMutation = useMutation({
mutationFn: deleteAsset,
@@ -127,16 +144,32 @@ const AssetLibrary: React.FC = () => {
message.warning('请先选择素材库');
return false;
}
// 文件大小校验:上限 2GB
if (file.size > MAX_FILE_SIZE) {
message.error('文件大小不能超过 2GB');
return false;
}
setUploading(true);
try {
const project = await getOrCreateDefaultProject();
const formData = new FormData();
formData.append('file', file);
formData.append('library_id', activeLibrary);
formData.append('project_id', project.id);
await uploadMutation.mutateAsync(formData);
if (file.size > LARGE_FILE_THRESHOLD) {
// 大文件(>100MB)走 OSS 预签名直传通道
await directUploadMutation.mutateAsync({
file,
library_id: activeLibrary,
});
} else {
// 小文件走表单上传
const project = await getOrCreateDefaultProject();
const formData = new FormData();
formData.append('file', file);
formData.append('library_id', activeLibrary);
formData.append('project_id', project.id);
await uploadMutation.mutateAsync(formData);
}
} catch {
// uploadMutation.onError 已处理错误提示
// mutation.onError 已处理错误提示
} finally {
setUploading(false);
}
@@ -216,7 +249,7 @@ const AssetLibrary: React.FC = () => {
beforeUpload={handleUpload}
showUploadList={false}
multiple
disabled={uploading || uploadMutation.isPending}
disabled={uploading || uploadMutation.isPending || directUploadMutation.isPending}
style={{ marginBottom: 24 }}
>
<p className="ant-upload-drag-icon">
@@ -226,7 +259,7 @@ const AssetLibrary: React.FC = () => {
{uploading ? '正在上传,请稍候...' : '点击或拖拽文件到此区域上传'}
</p>
<p className="ant-upload-hint">
支持 {kindLabel[currentLib?.kind || 'video']} 格式文件
支持 {kindLabel[currentLib?.kind || 'video']} 格式文件,单文件不超过 2GB
</p>
</Dragger>
)}