/* * Batch Download API List * /batchDownload/manage/list - GET * /batchDownload/manage/config - POST 创建新配置 * /batchDownload/manage/description/{id} - POST 更新任务说明 * /batchDownload/manage/owner/{id} - POST 设置owner * /batchDownload/manage/config/{id} - DELETE 删除配置 * /batchDownload/data/{id} - GET 获取指定ID的数据包下载地址 * /batchDownload/manage/path - GET 获取指定ID的文件目录结构 * /batchDownload/manage/fileTree - GET 获取指定文件的目录结构 * /batchDownload/manage/fileDownload - GET 下载指定文件 */ package controllers import ( "bufio" "fmt" "fwh-toolbox-server/domain" "fwh-toolbox-server/services" "fwh-toolbox-server/utils/mimetype" "path" "strconv" "strings" "github.com/gofiber/fiber/v2" "go.mongodb.org/mongo-driver/bson/primitive" "go.uber.org/zap" ) // 获取批量数据下载管理表 // /batchDownload/manage/list func GetBatchDownloadList(c *fiber.Ctx) error { pageInt, _ := strconv.Atoi(c.Query("pageNum", "1")) sizeInt, _ := strconv.Atoi(c.Query("pageSize", "20")) if pageInt <= 0 || sizeInt <= 0 { return Fail(c, "Invalid request para") } sn := c.Query("sn", "") progress := c.Query("progress", "") var p_sn *string = nil if sn != "" { p_sn = &sn } var p_progress *string = nil if progress != "" { p_progress = &progress } listPage, err := services.GetBatchDownloadManageList(uint(pageInt), uint(sizeInt), p_sn, p_progress) if err != nil { zap.L().Warn("Database read failed. (MongoDb)", zap.String("err", err.Error())) return Error(c, "Database read failed. (MongoDb)") } return Success(c, listPage) } // 创建一个批量数据下载管任务 // /batchDownload/manage/config func CreateBatchDownload(c *fiber.Ctx) error { var body domain.BatchDownloadConfigWrite if err := c.BodyParser(&body); err != nil { zap.L().Warn("Invalid request body", zap.String("err", err.Error())) return Fail(c, "Invalid request body") } if err := services.InsertBatchDownloadConfig(body); err != nil { zap.L().Warn("Database write failed. (MongoDb)", zap.String("err", err.Error())) return Error(c, "Database write failed. (MongoDb)") } return Success(c, body) } // 更新一个批量数据下载说明 // /batchDownload/manage/description/:id func UpdateBatchDownloadDescription(c *fiber.Ctx) error { id := c.Params("id") var body string if err := c.BodyParser(&body); err != nil { zap.L().Warn("Invalid request body", zap.String("err", err.Error())) return Fail(c, "Invalid request body") } objID, err := primitive.ObjectIDFromHex(id) if err != nil { zap.L().Warn("Invalid request para :id", zap.String("err", err.Error())) return Fail(c, "Invalid request para :id") } if err := services.UpdateBatchDownloadDescription(objID, body); err != nil { zap.L().Warn("Database write failed. (MongoDb)", zap.String("err", err.Error())) return Error(c, "Database write failed. (MongoDb)") } return Success(c, body) } // 设置一个批量数据的owner // /batchDownload/manage/owner/:id func UpdateBatchDownloadOwner(c *fiber.Ctx) error { id := c.Params("id") var body struct { Owner []string `json:"owner"` } if err := c.BodyParser(&body); err != nil { zap.L().Warn("Invalid request body", zap.String("err", err.Error())) return Fail(c, "Invalid request body") } objID, err := primitive.ObjectIDFromHex(id) if err != nil { zap.L().Warn("Invalid request para :id", zap.String("err", err.Error())) return Fail(c, "Invalid request para :id") } if err := services.UpdateBatchDownloadOwner(objID, body.Owner); err != nil { zap.L().Warn("Database write failed. (MongoDb)", zap.String("err", err.Error())) return Error(c, "Database write failed. (MongoDb)") } return Success(c, body) } // 删除一个批量数据下载数据 // /batchDownload/manage/config/:id func DeleteBatchDownload(c *fiber.Ctx) error { id := c.Params("id") objID, err := primitive.ObjectIDFromHex(id) if err != nil { zap.L().Warn("Invalid request para :id", zap.String("err", err.Error())) return Fail(c, "Invalid request para :id") } err = services.DeleteBatchDownloadConfig(objID) if err != nil { zap.L().Warn("Database delete failed. (MongoDb)", zap.String("err", err.Error())) return Error(c, "Database delete failed. (MongoDb)") } return NoContent(c) } // 获取指定ID的批量数据下载数据包地址 // /batchDownload/data/:id func GetBatchDownloadData(c *fiber.Ctx) error { id := c.Params("id") objID, err := primitive.ObjectIDFromHex(id) if err != nil { zap.L().Warn("Invalid request para :id", zap.String("err", err.Error())) return Fail(c, "Invalid request para :id") } c.Set("Content-Type", "application/zip") c.Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"BatchDownload_%s.zip\"", id)) // Fiber 原生 Context 的 BodyWriter,可直接写数据到 HTTP 输出 // writer := c.Context().Response.BodyWriter() // 使用 SetBodyStreamWriter 流式写入 c.Context().SetBodyStreamWriter(func(w *bufio.Writer) { err = services.GetBatchDownloadData(objID, w) if err != nil { zap.L().Warn("Database read failed. (MongoDb)", zap.String("err", err.Error())) return } w.Flush() fmt.Println("SetBodyStreamWriter complete.") }) return nil } // 获取指定ID的文件目录结构 // /batchDownload/manage/path func GetBatchDownloadPath(c *fiber.Ctx) error { id := c.Query("id", "") objID, err := primitive.ObjectIDFromHex(id) if err != nil { zap.L().Warn("Invalid request para :id", zap.String("err", err.Error())) return Fail(c, "Invalid request para :id") } pathInfo, err := services.GetBatchDownloadPath(objID) if err != nil { zap.L().Warn("Path query failed.", zap.String("err", err.Error())) return Error(c, "Path query failed.") } return Success(c, pathInfo) } // 获取指定文件的目录结构 // /batchDownload/manage/fileTree func GetBatchDownloadFileTree(c *fiber.Ctx) error { filePath := c.Query("file", "") pathInfo, err := services.GetBatchDownloadFileTree(filePath) if err != nil { zap.L().Warn("File tree query failed.", zap.String("err", err.Error())) return Error(c, "File tree query failed.") } return Success(c, pathInfo) } // 下载指定文件 // /batchDownload/manage/fileDownload func GetBatchDownloadFileDownload(c *fiber.Ctx) error { filePath := c.Query("file", "") innerPath := c.Query("inner", "") var fileName string if innerPath == "" { fileName = path.Base(filePath) } else { if !strings.HasSuffix(filePath, ".tar.gz") { return Error(c, "File path suffix not is \".tar.gz\".") } fileName = path.Base(innerPath) } if fileName == "." { return Error(c, "File path is empty.") } else if fileName == "/" { return Error(c, "File path consists entirely of slashes.") } c.Set("Content-Type", mimetype.GetContentType(fileName)) c.Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", fileName)) // Fiber 原生 Context 的 BodyWriter,可直接写数据到 HTTP 输出 // writer := c.Context().Response.BodyWriter() // 使用 SetBodyStreamWriter 流式写入 c.Context().SetBodyStreamWriter(func(w *bufio.Writer) { err := services.GetBatchDownloadFileDownload(filePath, innerPath, w) if err != nil { zap.L().Warn("File read failed.", zap.String("err", err.Error())) return } w.Flush() fmt.Println("SetBodyStreamWriter complete.") }) return nil }