Просмотр исходного кода

✨ feat(file): 添加多部分上传策略支持
- 实现createMultipartUploadPolicy方法,支持大文件分片上传
- 生成唯一文件ID和存储路径
- 初始化多部分上传并生成各部分上传URL
- 保存文件记录到数据库并返回上传策略信息

♻️ refactor(file): 修改文件ID类型为数字
- 将getFileUrl和deleteFile方法的id参数类型从string改为number
- 更新文件路由参数验证,使用z.coerce.number()确保ID为数字类型
- 调整参数示例为数字类型

yourname 8 месяцев назад
Родитель
Сommit
85f35ccdb1
2 измененных файлов с 55 добавлено и 4 удалено
  1. 3 2
      src/server/api/files/[id]/get-url.ts
  2. 52 2
      src/server/modules/files/file.service.ts

+ 3 - 2
src/server/api/files/[id]/get-url.ts

@@ -1,5 +1,6 @@
 import { createRoute, OpenAPIHono, z } from '@hono/zod-openapi';
 import { FileService } from '@/server/modules/files/file.service';
+import { MinioService } from '@/server/modules/files/minio.service';
 import { ErrorSchema } from '@/server/utils/errorHandler';
 import { AppDataSource } from '@/server/data-source';
 import { AuthContext } from '@/server/types/context';
@@ -12,9 +13,9 @@ const getFileUrlRoute = createRoute({
   middleware: [authMiddleware],
   request: {
     params: z.object({
-      id: z.string().openapi({
+      id: z.coerce.number().openapi({
         param: { name: 'id', in: 'path' },
-        example: 'FILE123456',
+        example: 1,
         description: '文件ID'
       })
     })

+ 52 - 2
src/server/modules/files/file.service.ts

@@ -53,7 +53,7 @@ export class FileService extends GenericCrudService<File> {
   /**
    * 删除文件记录及对应的MinIO文件
    */
-  async deleteFile(id: string) {
+  async deleteFile(id: number) {
     try {
       // 获取文件记录
       const file = await this.getById(id);
@@ -77,7 +77,7 @@ export class FileService extends GenericCrudService<File> {
   /**
    * 获取文件访问URL
    */
-  async getFileUrl(id: string) {
+  async getFileUrl(id: number) {
     const file = await this.getById(id);
     if (!file) {
       throw new Error('文件不存在');
@@ -85,4 +85,54 @@ export class FileService extends GenericCrudService<File> {
     
     return this.minioService.getFileUrl(this.minioService.bucketName, file.path);
   }
+
+  /**
+   * 创建多部分上传策略
+   */
+  async createMultipartUploadPolicy(data: Partial<File>, partCount: number) {
+    try {
+      // 生成唯一文件ID和存储路径
+      const fileId = `FILE${Date.now()}${Math.floor(Math.random() * 1000)}`;
+      const fileKey = `${data.uploadUserId}/${uuidv4()}-${data.name}`;
+      
+      // 初始化多部分上传
+      const uploadId = await this.minioService.createMultipartUpload(
+        this.minioService.bucketName,
+        fileKey
+      );
+      
+      // 生成各部分上传URL
+      const uploadUrls = await this.minioService.generateMultipartUploadUrls(
+        this.minioService.bucketName,
+        fileKey,
+        uploadId,
+        partCount
+      );
+      
+      // 准备文件记录数据
+      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,
+        uploadId,
+        uploadUrls,
+        bucket: this.minioService.bucketName,
+        key: fileKey
+      };
+    } catch (error) {
+      logger.error('Failed to create multipart upload policy:', error);
+      throw new Error('创建多部分上传策略失败');
+    }
+  }
 }