package controller import ( "fmt" "seeyon-filesystem/dto" "seeyon-filesystem/middleware" "seeyon-filesystem/service" "seeyon-filesystem/utils" "github.com/gin-gonic/gin" ) // ChunkUploadController 分片上传控制器 type ChunkUploadController struct { chunkService *service.ChunkUploadService } func NewChunkUploadController() *ChunkUploadController { return &ChunkUploadController{ chunkService: service.NewChunkUploadService(), } } // Init 初始化分片上传 // POST /api/file/upload/init func (c *ChunkUploadController) Init(ctx *gin.Context) { ownerID := middleware.GetCurrentUserID(ctx) var req dto.ChunkUploadInitRequest if err := ctx.ShouldBindJSON(&req); err != nil { utils.BadRequest(ctx, "参数错误: "+err.Error()) return } result, err := c.chunkService.InitUpload(req.FileName, req.FileSize, req.MD5, uint64(req.FolderID), ownerID, req.PolicyID) if err != nil { utils.ServerError(ctx, err.Error()) return } utils.Success(ctx, result) } // UploadChunk 上传单个分片 // PUT /api/file/upload/chunk/:uploadId/:index func (c *ChunkUploadController) UploadChunk(ctx *gin.Context) { uploadID := ctx.Param("uploadId") indexStr := ctx.Param("index") var index int if _, err := fmt.Sscanf(indexStr, "%d", &index); err != nil { utils.BadRequest(ctx, "分片索引无效") return } checksum := ctx.GetHeader("X-Checksum") file, err := ctx.FormFile("chunk") if err != nil { // 尝试从body读取 utils.BadRequest(ctx, "请上传分片文件") return } reader, err := file.Open() if err != nil { utils.BadRequest(ctx, "读取分片失败") return } defer reader.Close() result, err := c.chunkService.UploadChunk(uploadID, index, reader, checksum) if err != nil { utils.BadRequest(ctx, err.Error()) return } utils.Success(ctx, result) } // ConfirmChunk 确认MinIO分片上传完成(客户端直传后调用) // POST /api/file/upload/chunk/:uploadId/:index/confirm func (c *ChunkUploadController) ConfirmChunk(ctx *gin.Context) { uploadID := ctx.Param("uploadId") indexStr := ctx.Param("index") var index int if _, err := fmt.Sscanf(indexStr, "%d", &index); err != nil { utils.BadRequest(ctx, "分片索引无效") return } var req struct { ETag string `json:"etag"` } ctx.ShouldBindJSON(&req) result, err := c.chunkService.UploadChunkMinIO(uploadID, index, req.ETag) if err != nil { utils.BadRequest(ctx, err.Error()) return } utils.Success(ctx, result) } // Merge 合并分片完成上传 // POST /api/file/upload/merge/:uploadId func (c *ChunkUploadController) Merge(ctx *gin.Context) { uploadID := ctx.Param("uploadId") result, err := c.chunkService.MergeChunks(uploadID) if err != nil { utils.ServerError(ctx, err.Error()) return } utils.Success(ctx, result) } // Progress 查询上传进度 // GET /api/file/upload/progress/:uploadId func (c *ChunkUploadController) Progress(ctx *gin.Context) { uploadID := ctx.Param("uploadId") result, err := c.chunkService.GetUploadProgress(uploadID) if err != nil { utils.NotFound(ctx, err.Error()) return } utils.Success(ctx, result) } // Cancel 取消上传 // DELETE /api/file/upload/:uploadId func (c *ChunkUploadController) Cancel(ctx *gin.Context) { uploadID := ctx.Param("uploadId") if err := c.chunkService.CancelUpload(uploadID); err != nil { utils.BadRequest(ctx, err.Error()) return } utils.SuccessWithMessage(ctx, "已取消", nil) }