LicenseManger/internal/api/upload.go

214 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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": "文件上传成功",
})
}