|
|
@@ -1,9 +1,88 @@
|
|
|
import { GenericCrudService } from '@/server/utils/generic-crud.service';
|
|
|
import { DataSource } from 'typeorm';
|
|
|
import { File } from './file.entity';
|
|
|
+import { MinioService } from './minio.service';
|
|
|
+// import { AppError } from '@/server/utils/errorHandler';
|
|
|
+import { v4 as uuidv4 } from 'uuid';
|
|
|
+import { logger } from '@/server/utils/logger';
|
|
|
|
|
|
export class FileService extends GenericCrudService<File> {
|
|
|
+ private readonly minioService: MinioService;
|
|
|
+
|
|
|
constructor(dataSource: DataSource) {
|
|
|
super(dataSource, File);
|
|
|
+ this.minioService = new MinioService();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建文件记录并生成预签名上传URL
|
|
|
+ */
|
|
|
+ async createFile(data: Partial<File>) {
|
|
|
+ try {
|
|
|
+ // 生成唯一文件ID和存储路径
|
|
|
+ const fileId = `FILE${Date.now()}${Math.floor(Math.random() * 1000)}`;
|
|
|
+ const fileKey = `${data.uploadUserId}/${uuidv4()}-${data.name}`;
|
|
|
+
|
|
|
+ // 生成MinIO上传策略
|
|
|
+ const uploadPolicy = await this.minioService.generateUploadPolicy(fileKey);
|
|
|
+
|
|
|
+ // 准备文件记录数据
|
|
|
+ const fileData = {
|
|
|
+ ...data,
|
|
|
+ id: fileId,
|
|
|
+ path: fileKey,
|
|
|
+ uploadTime: new Date(),
|
|
|
+ createdAt: new Date(),
|
|
|
+ updatedAt: new Date()
|
|
|
+ };
|
|
|
+
|
|
|
+ // 保存文件记录到数据库
|
|
|
+ const savedFile = await this.create(fileData as File);
|
|
|
+
|
|
|
+ // 返回文件记录和上传策略
|
|
|
+ return {
|
|
|
+ file: savedFile,
|
|
|
+ uploadPolicy
|
|
|
+ };
|
|
|
+ } catch (error) {
|
|
|
+ logger.error('Failed to create file:', error);
|
|
|
+ throw new Error('文件创建失败');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除文件记录及对应的MinIO文件
|
|
|
+ */
|
|
|
+ async deleteFile(id: string) {
|
|
|
+ try {
|
|
|
+ // 获取文件记录
|
|
|
+ const file = await this.getById(id);
|
|
|
+ if (!file) {
|
|
|
+ throw new Error('文件不存在');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从MinIO删除文件
|
|
|
+ await this.minioService.deleteObject(this.minioService.bucketName, file.path);
|
|
|
+
|
|
|
+ // 从数据库删除记录
|
|
|
+ await this.delete(id);
|
|
|
+
|
|
|
+ return true;
|
|
|
+ } catch (error) {
|
|
|
+ logger.error('Failed to delete file:', error);
|
|
|
+ throw new Error('文件删除失败');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取文件访问URL
|
|
|
+ */
|
|
|
+ async getFileUrl(id: string) {
|
|
|
+ const file = await this.getById(id);
|
|
|
+ if (!file) {
|
|
|
+ throw new Error('文件不存在');
|
|
|
+ }
|
|
|
+
|
|
|
+ return this.minioService.getFileUrl(this.minioService.bucketName, file.path);
|
|
|
}
|
|
|
}
|