Files
seclusion/apps/web/src/services/file.service.ts
charilezhou 58529f0321 feat: 添加文件上传功能
后端:
- 新增 StorageService 集成 MinIO 对象存储
- 新增 FileService 和 FileController 处理文件上传
- 支持头像上传场景,含文件类型和大小验证
- 支持生成临时访问 URL

前端:
- 新增 AvatarUpload 组件,支持拖拽和点击上传
- 新增 useUploadAvatar 和 useFileUrl hooks
- 新增 file.service.ts 封装文件 API

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 12:34:58 +08:00

71 lines
1.5 KiB
TypeScript

import { API_ENDPOINTS } from '@/config/constants';
import { httpClient, type CustomRequestConfig } from '@/lib/http';
/** 文件用途 */
export type FilePurpose = 'avatar' | 'attachment';
/** 文件响应 */
export interface FileResponse {
id: string;
filename: string;
mimeType: string;
size: number;
purpose: string;
createdAt: string;
}
/** 临时访问 URL 响应 */
export interface PresignedUrlResponse {
url: string;
expiresIn: number;
}
/**
* 上传文件
*/
export async function uploadFile(
file: File,
purpose: FilePurpose,
): Promise<FileResponse> {
const formData = new FormData();
formData.append('file', file);
formData.append('purpose', purpose);
const config: CustomRequestConfig = {
headers: {
'Content-Type': 'multipart/form-data',
},
skipEncryption: true,
};
const response = await httpClient.post<FileResponse>(
`${API_ENDPOINTS.FILES}/upload`,
formData,
config,
);
return response.data;
}
/**
* 获取文件临时访问 URL
*/
export async function getFileUrl(
fileId: string,
expiresIn?: number,
): Promise<PresignedUrlResponse> {
const params = expiresIn ? { expiresIn } : {};
const response = await httpClient.get<PresignedUrlResponse>(
`${API_ENDPOINTS.FILES}/${fileId}/url`,
{ params },
);
return response.data;
}
/**
* 删除文件
*/
export async function deleteFile(fileId: string): Promise<void> {
await httpClient.delete(`${API_ENDPOINTS.FILES}/${fileId}`);
}