214 lines
5.1 KiB
Go
214 lines
5.1 KiB
Go
package api
|
||
|
||
import (
|
||
"fmt"
|
||
"licserver/internal/service"
|
||
"net/http"
|
||
"os"
|
||
"path/filepath"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
type UploadHandler struct {
|
||
uploadService *service.UploadService
|
||
}
|
||
|
||
func NewUploadHandler(uploadService *service.UploadService) *UploadHandler {
|
||
return &UploadHandler{uploadService: uploadService}
|
||
}
|
||
|
||
func (h *UploadHandler) UploadFile(c *gin.Context) {
|
||
file, err := c.FormFile("file")
|
||
if err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "未找到上传文件"})
|
||
return
|
||
}
|
||
|
||
deviceUID := c.PostForm("device_uid")
|
||
description := c.PostForm("description")
|
||
userID := c.GetUint("userID")
|
||
|
||
upload, err := h.uploadService.UploadFile(file, userID, deviceUID, description)
|
||
if err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
|
||
c.JSON(http.StatusOK, upload)
|
||
}
|
||
|
||
func (h *UploadHandler) DownloadFile(c *gin.Context) {
|
||
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||
if err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的文件ID"})
|
||
return
|
||
}
|
||
|
||
file, err := h.uploadService.DownloadFile(uint(id))
|
||
if err != nil {
|
||
c.JSON(http.StatusNotFound, gin.H{"error": "文件不存在"})
|
||
return
|
||
}
|
||
|
||
c.FileAttachment(file.FilePath, file.FileName)
|
||
}
|
||
|
||
func (h *UploadHandler) DeleteFile(c *gin.Context) {
|
||
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||
if err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的文件ID"})
|
||
return
|
||
}
|
||
|
||
userID := c.GetUint("userID")
|
||
if err := h.uploadService.DeleteFile(uint(id), userID); err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
|
||
c.JSON(http.StatusOK, gin.H{"message": "文件删除成功"})
|
||
}
|
||
|
||
func (h *UploadHandler) GetDeviceFiles(c *gin.Context) {
|
||
deviceUID := c.Param("uid")
|
||
files, err := h.uploadService.GetDeviceFiles(deviceUID)
|
||
if err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
|
||
c.JSON(http.StatusOK, files)
|
||
}
|
||
|
||
func (h *UploadHandler) UploadChunk(c *gin.Context) {
|
||
file, err := c.FormFile("chunk")
|
||
if err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "未找到上传文件"})
|
||
return
|
||
}
|
||
|
||
fileHash := c.PostForm("fileHash")
|
||
if fileHash == "" {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "未提供文件哈希"})
|
||
return
|
||
}
|
||
|
||
chunkNumber, err := strconv.Atoi(c.PostForm("chunkNumber"))
|
||
if err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的分片序号"})
|
||
return
|
||
}
|
||
|
||
totalChunks, err := strconv.Atoi(c.PostForm("totalChunks"))
|
||
if err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的总分片数"})
|
||
return
|
||
}
|
||
|
||
totalSize, err := strconv.ParseInt(c.PostForm("totalSize"), 10, 64)
|
||
if err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的文件大小"})
|
||
return
|
||
}
|
||
|
||
filename := c.PostForm("filename")
|
||
deviceUID := c.PostForm("deviceUID")
|
||
userID := c.GetUint("userID")
|
||
|
||
err = h.uploadService.UploadChunk(
|
||
file,
|
||
fileHash,
|
||
chunkNumber,
|
||
totalChunks,
|
||
totalSize,
|
||
filename,
|
||
userID,
|
||
deviceUID,
|
||
)
|
||
|
||
if err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
|
||
// 检查是否所有分片都已上传
|
||
completed, err := h.uploadService.CheckUploadStatus(fileHash)
|
||
if err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"message": "分片上传成功",
|
||
"completed": completed,
|
||
})
|
||
}
|
||
|
||
func (h *UploadHandler) MergeChunks(c *gin.Context) {
|
||
fileHash := c.PostForm("fileHash")
|
||
if fileHash == "" {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "未提供文件哈希"})
|
||
return
|
||
}
|
||
|
||
upload, err := h.uploadService.MergeChunks(fileHash)
|
||
if err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
return
|
||
}
|
||
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"message": "文件合并成功",
|
||
"file": upload,
|
||
})
|
||
}
|
||
|
||
func (h *UploadHandler) UploadSiteFile(c *gin.Context) {
|
||
file, err := c.FormFile("file")
|
||
if err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "未找到上传文件"})
|
||
return
|
||
}
|
||
|
||
// 检查文件类型
|
||
ext := strings.ToLower(filepath.Ext(file.Filename))
|
||
allowedExts := map[string]bool{
|
||
".jpg": true, ".jpeg": true, ".png": true, ".gif": true,
|
||
".ico": true, ".svg": true,
|
||
}
|
||
if !allowedExts[ext] {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "不支持的文件类型"})
|
||
return
|
||
}
|
||
|
||
// 生成文件名
|
||
filename := fmt.Sprintf("site_%s%s", time.Now().Format("20060102150405"), ext)
|
||
|
||
// 构建目标目录路径
|
||
uploadDir := filepath.Join("web", "static", "images")
|
||
if err := os.MkdirAll(uploadDir, 0755); err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建目录失败"})
|
||
return
|
||
}
|
||
|
||
// 构建完整的文件路径
|
||
filePath := filepath.Join(uploadDir, filename)
|
||
|
||
// 保存文件
|
||
if err := c.SaveUploadedFile(file, filePath); err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": "保存文件失败"})
|
||
return
|
||
}
|
||
|
||
// 返回文件URL(使用正斜杠作为URL路径分隔符)
|
||
fileURL := "/" + strings.Join([]string{"static", "images", filename}, "/")
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"url": fileURL,
|
||
"message": "文件上传成功",
|
||
})
|
||
}
|