mirror of
https://github.com/keven1024/015.git
synced 2026-05-26 07:08:02 +00:00
feat(backend): implement file upload functionality with task creation, slice upload, and completion handling
This commit is contained in:
156
backend/controllers/file.go
Normal file
156
backend/controllers/file.go
Normal file
@@ -0,0 +1,156 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"backend/internal/models"
|
||||
"backend/internal/service"
|
||||
"backend/internal/utils"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func CreateUploadTask(c echo.Context) error {
|
||||
// cc := c.(*middleware.CustomContext)
|
||||
r := new(models.FileInfo)
|
||||
if err := c.Bind(r); err != nil {
|
||||
return utils.HTTPErrorHandler(c, err)
|
||||
}
|
||||
|
||||
if r.FileSize == 0 || r.MimeType == "" || r.FileHash == "" {
|
||||
return utils.HTTPErrorHandler(c, errors.New("上传文件信息不完整"))
|
||||
}
|
||||
rdb, ctx := utils.GetRedisClient()
|
||||
fileId := service.GetFileId(r.FileHash, r.FileSize)
|
||||
fileInfo, _ := service.GetRedisFileInfo(fileId)
|
||||
|
||||
if fileInfo != (models.RedisFileInfo{}) {
|
||||
return utils.HTTPSuccessHandler(c, map[string]any{
|
||||
"size": fileInfo.FileSize,
|
||||
"mime_type": fileInfo.MimeType,
|
||||
"hash": fileInfo.FileHash,
|
||||
"type": fileInfo.FileType,
|
||||
"expire": fileInfo.Expire,
|
||||
"id": fileId,
|
||||
})
|
||||
}
|
||||
|
||||
newFileInfo := models.RedisFileInfo{
|
||||
FileType: models.FileTypeInit,
|
||||
FileInfo: models.FileInfo{
|
||||
FileSize: r.FileSize,
|
||||
MimeType: r.MimeType,
|
||||
FileHash: r.FileHash,
|
||||
},
|
||||
CreatedAt: time.Now().Unix(),
|
||||
Expire: 3600,
|
||||
}
|
||||
jsonData, _ := json.Marshal(newFileInfo)
|
||||
rdb.HSet(ctx, "015:fileInfoMap", fileId, string(jsonData)).Result()
|
||||
|
||||
return utils.HTTPSuccessHandler(c, map[string]any{
|
||||
"size": newFileInfo.FileSize,
|
||||
"mime_type": newFileInfo.MimeType,
|
||||
"hash": newFileInfo.FileHash,
|
||||
"type": newFileInfo.FileType,
|
||||
"expire": newFileInfo.Expire,
|
||||
"id": fileId,
|
||||
})
|
||||
}
|
||||
|
||||
type UploadFileSliceProps struct {
|
||||
FileId string `form:"id"`
|
||||
FileIndex int64 `form:"index"`
|
||||
FileSlice *multipart.FileHeader `form:"file"`
|
||||
}
|
||||
|
||||
func UploadFileSlice(c echo.Context) error {
|
||||
r := new(UploadFileSliceProps)
|
||||
if err := c.Bind(r); err != nil {
|
||||
return utils.HTTPErrorHandler(c, err)
|
||||
}
|
||||
|
||||
if r.FileId == "" || r.FileIndex == 0 || r.FileSlice == nil {
|
||||
return utils.HTTPErrorHandler(c, errors.New("上传文件信息不完整"))
|
||||
}
|
||||
_, err := service.GetRedisFileInfo(r.FileId)
|
||||
|
||||
if err != nil {
|
||||
return utils.HTTPErrorHandler(c, err)
|
||||
}
|
||||
|
||||
src, err := r.FileSlice.Open()
|
||||
if err != nil {
|
||||
return utils.HTTPErrorHandler(c, err)
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
uploadPath, err := service.GetUploadDirPath()
|
||||
if err != nil {
|
||||
return utils.HTTPErrorHandler(c, err)
|
||||
}
|
||||
|
||||
filePath := filepath.Join(uploadPath, r.FileId)
|
||||
if err := os.MkdirAll(filePath, 0755); err != nil {
|
||||
return utils.HTTPErrorHandler(c, errors.New("创建上传目录失败"))
|
||||
}
|
||||
|
||||
dst, err := os.Create(filepath.Join(filePath, fmt.Sprintf("%d", r.FileIndex)))
|
||||
if err != nil {
|
||||
return utils.HTTPErrorHandler(c, err)
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
if _, err = io.Copy(dst, src); err != nil {
|
||||
return utils.HTTPErrorHandler(c, err)
|
||||
}
|
||||
|
||||
return utils.HTTPSuccessHandler(c, map[string]any{
|
||||
"message": "成功上传",
|
||||
})
|
||||
}
|
||||
|
||||
type FinishUploadTaskProps struct {
|
||||
FileId string `json:"id"`
|
||||
}
|
||||
|
||||
func FinishUploadTask(c echo.Context) error {
|
||||
r := new(FinishUploadTaskProps)
|
||||
if err := c.Bind(r); err != nil {
|
||||
return utils.HTTPErrorHandler(c, err)
|
||||
}
|
||||
|
||||
if r.FileId == "" {
|
||||
return utils.HTTPErrorHandler(c, errors.New("文件ID不能为空"))
|
||||
}
|
||||
|
||||
fileInfo, err := service.GetRedisFileInfo(r.FileId)
|
||||
if err != nil {
|
||||
return utils.HTTPErrorHandler(c, err)
|
||||
}
|
||||
|
||||
if fileInfo.FileType != models.FileTypeInit {
|
||||
return utils.HTTPErrorHandler(c, errors.New("task状态错误"))
|
||||
}
|
||||
|
||||
// 合并文件切片
|
||||
if err := service.MergeFileSlices(r.FileId); err != nil {
|
||||
return utils.HTTPErrorHandler(c, err)
|
||||
}
|
||||
|
||||
// 更新文件状态
|
||||
// fileInfo.FileType = models.FileTypeComplete
|
||||
if err := service.MergeFileSlices(r.FileId); err != nil {
|
||||
return utils.HTTPErrorHandler(c, err)
|
||||
}
|
||||
|
||||
return utils.HTTPSuccessHandler(c, map[string]any{
|
||||
"message": "文件上传完成并合并成功",
|
||||
})
|
||||
}
|
||||
28
backend/internal/models/file.go
Normal file
28
backend/internal/models/file.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package models
|
||||
|
||||
type FileInfo struct {
|
||||
FileSize int64 `json:"size"`
|
||||
MimeType string `json:"mime_type"`
|
||||
FileHash string `json:"hash"`
|
||||
}
|
||||
|
||||
type FileType string
|
||||
|
||||
const (
|
||||
FileTypeInit FileType = "init"
|
||||
FileTypeUpload FileType = "already"
|
||||
)
|
||||
|
||||
type RedisFileInfo struct {
|
||||
FileInfo
|
||||
FileType FileType `json:"type"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
Expire int64 `json:"expire"`
|
||||
}
|
||||
|
||||
type RedisShareInfo struct {
|
||||
Id string `json:"id"`
|
||||
Owner string `json:"owner"`
|
||||
FileId string `json:"fileId"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
@@ -1,15 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"backend/controllers"
|
||||
|
||||
"backend/middleware"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func main() {
|
||||
e := echo.New()
|
||||
e.GET("/", func(c echo.Context) error {
|
||||
return c.String(http.StatusOK, "Hello, World!")
|
||||
})
|
||||
e.Use(middleware.ContextMiddleware())
|
||||
e.Use(middleware.SessionMiddleware())
|
||||
e.Use(middleware.AuthMiddleware())
|
||||
|
||||
// e.GET("/file/:id", controllers.GetFile)
|
||||
e.POST("/file/create", controllers.CreateUploadTask)
|
||||
e.POST("/file/slice", controllers.UploadFileSlice)
|
||||
e.POST("/file/finish", controllers.FinishUploadTask)
|
||||
|
||||
e.Logger.Fatal(e.Start(":1323"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user