Files
nl-blogs/server/handlers/attachment.go
2026-01-19 16:14:08 +08:00

448 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handlers
import (
"log"
"strconv"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
// AdminUploadAttachment 上传附件
func AdminUploadAttachment(c *gin.Context) {
// 获取文件
file, err := c.FormFile("file")
if err != nil {
utils.Error(c, 400, "No file uploaded")
return
}
// 获取分类ID可选
categoryIDStr := c.PostForm("categoryId")
var categoryID *uint
if categoryIDStr != "" {
if id, err := strconv.ParseUint(categoryIDStr, 10, 32); err == nil {
idUint := uint(id)
categoryID = &idUint
}
}
// 获取存储类型
storageType := c.DefaultPostForm("storageType", "local")
// 打开文件
src, err := file.Open()
if err != nil {
utils.Error(c, 500, "Failed to open file")
return
}
defer src.Close()
// 获取OSS配置
var ossConfig *models.OSSConfig
if storageType != "local" {
ossConfig, err = repositories.GetActiveOSSConfig(storageType)
if err != nil || ossConfig == nil {
utils.Error(c, 400, "OSS config not found or not active")
return
}
}
// 创建OSS配置对象
config := &utils.OSSConfig{
StorageType: storageType,
}
if ossConfig != nil {
// 解密AccessKey和SecretKey
accessKey, err := utils.DecryptAES(ossConfig.AccessKey)
if err != nil {
log.Printf("Failed to decrypt access key: %v", err)
utils.Error(c, 500, "Failed to decrypt OSS credentials")
return
}
secretKey, err := utils.DecryptAES(ossConfig.SecretKey)
if err != nil {
log.Printf("Failed to decrypt secret key: %v", err)
utils.Error(c, 500, "Failed to decrypt OSS credentials")
return
}
config.AccessKey = accessKey
config.SecretKey = secretKey
config.Bucket = ossConfig.Bucket
config.Region = ossConfig.Region
config.Domain = ossConfig.Domain
}
// 获取上传器
uploader, err := utils.GetOSSUploader(config)
if err != nil {
utils.Error(c, 500, err.Error())
return
}
// 上传文件
filePath, fileURL, err := uploader.Upload(src, file.Filename, file.Size)
if err != nil {
utils.Error(c, 500, "Failed to upload file: "+err.Error())
return
}
// 获取文件类型
fileType := utils.GetFileType(file.Header.Get("Content-Type"))
// 创建附件记录
attachment := &models.Attachment{
CategoryID: categoryID,
OriginalName: file.Filename,
StoredName: file.Filename,
FilePath: filePath,
FileURL: fileURL,
FileSize: file.Size,
FileType: fileType,
MimeType: file.Header.Get("Content-Type"),
StorageType: storageType,
}
if ossConfig != nil {
ossConfigID := ossConfig.ID
attachment.OSSConfigID = &ossConfigID
}
if err := repositories.CreateAttachment(attachment); err != nil {
// 如果数据库保存失败,尝试删除已上传的文件
uploader.Delete(filePath)
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "File uploaded successfully", attachment)
}
// AdminGetAttachments 获取附件列表
func AdminGetAttachments(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "20"))
categoryIDStr := c.Query("categoryId")
fileType := c.Query("fileType")
var categoryID *uint
if categoryIDStr != "" {
if id, err := strconv.ParseUint(categoryIDStr, 10, 32); err == nil {
idUint := uint(id)
categoryID = &idUint
}
}
attachments, total, err := repositories.GetAttachments(page, pageSize, categoryID, fileType)
if err != nil {
utils.ServerError(c, err)
return
}
res := gin.H{
"list": attachments,
"total": total,
"page": page,
"size": pageSize,
}
utils.Success(c, res)
}
// AdminDeleteAttachment 删除附件
func AdminDeleteAttachment(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := strconv.ParseUint(idStr, 10, 32); err != nil {
utils.Error(c, 400, "Invalid attachment ID")
return
}
// 获取附件信息
attachment, err := repositories.GetAttachmentByID(id)
if err != nil || attachment == nil {
utils.Error(c, 404, "Attachment not found")
return
}
// 获取OSS配置并删除文件
if attachment.StorageType != "" {
var ossConfig *models.OSSConfig
if attachment.OSSConfigID != nil {
ossConfig, err = repositories.GetOSSConfigByID(*attachment.OSSConfigID)
} else {
ossConfig, err = repositories.GetActiveOSSConfig(attachment.StorageType)
}
if err == nil && ossConfig != nil {
config := &utils.OSSConfig{
StorageType: attachment.StorageType,
}
// 解密密钥
if accessKey, err := utils.DecryptAES(ossConfig.AccessKey); err == nil {
config.AccessKey = accessKey
}
if secretKey, err := utils.DecryptAES(ossConfig.SecretKey); err == nil {
config.SecretKey = secretKey
}
config.Bucket = ossConfig.Bucket
config.Region = ossConfig.Region
config.Domain = ossConfig.Domain
uploader, err := utils.GetOSSUploader(config)
if err == nil {
uploader.Delete(attachment.FilePath)
}
}
}
// 删除数据库记录
if err := repositories.DeleteAttachment(id); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Attachment deleted successfully", nil)
}
// AdminGetAttachmentCategories 获取附件分类列表
func AdminGetAttachmentCategories(c *gin.Context) {
categories, err := repositories.GetAttachmentCategories()
if err != nil {
utils.ServerError(c, err)
return
}
utils.Success(c, categories)
}
// AdminCreateAttachmentCategory 创建附件分类
func AdminCreateAttachmentCategory(c *gin.Context) {
var category models.AttachmentCategory
if err := c.ShouldBindJSON(&category); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
if err := repositories.CreateAttachmentCategory(&category); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Category created successfully", category)
}
// AdminUpdateAttachmentCategory 更新附件分类
func AdminUpdateAttachmentCategory(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := strconv.ParseUint(idStr, 10, 32); err != nil {
utils.Error(c, 400, "Invalid category ID")
return
}
var category models.AttachmentCategory
if err := c.ShouldBindJSON(&category); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
category.ID = id
if err := repositories.UpdateAttachmentCategory(&category); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Category updated successfully", nil)
}
// AdminDeleteAttachmentCategory 删除附件分类
func AdminDeleteAttachmentCategory(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := strconv.ParseUint(idStr, 10, 32); err != nil {
utils.Error(c, 400, "Invalid category ID")
return
}
if err := repositories.DeleteAttachmentCategory(id); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Category deleted successfully", nil)
}
// AdminGetOSSConfigs 获取OSS配置列表
func AdminGetOSSConfigs(c *gin.Context) {
configs, err := repositories.GetOSSConfigs()
if err != nil {
utils.ServerError(c, err)
return
}
// 不返回加密的密钥
for i := range configs {
configs[i].AccessKey = "***"
configs[i].SecretKey = "***"
}
utils.Success(c, configs)
}
// AdminCreateOSSConfig 创建OSS配置
func AdminCreateOSSConfig(c *gin.Context) {
var req struct {
Name string `json:"name" binding:"required"`
StorageType string `json:"storageType" binding:"required"`
AccessKey string `json:"accessKey" binding:"required"`
SecretKey string `json:"secretKey" binding:"required"`
Bucket string `json:"bucket"`
Region string `json:"region"`
Domain string `json:"domain"`
IsActive int `json:"isActive"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
// 加密密钥
encryptedAccessKey, err := utils.EncryptAES(req.AccessKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt access key")
return
}
encryptedSecretKey, err := utils.EncryptAES(req.SecretKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt secret key")
return
}
ossConfig := &models.OSSConfig{
Name: req.Name,
StorageType: req.StorageType,
AccessKey: encryptedAccessKey,
SecretKey: encryptedSecretKey,
Bucket: req.Bucket,
Region: req.Region,
Domain: req.Domain,
IsActive: req.IsActive,
}
if err := repositories.CreateOSSConfig(ossConfig); err != nil {
utils.ServerError(c, err)
return
}
// 不返回加密的密钥
ossConfig.AccessKey = "***"
ossConfig.SecretKey = "***"
utils.SuccessWithMsg(c, "OSS config created successfully", ossConfig)
}
// AdminUpdateOSSConfig 更新OSS配置
func AdminUpdateOSSConfig(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := strconv.ParseUint(idStr, 10, 32); err != nil {
utils.Error(c, 400, "Invalid OSS config ID")
return
}
var req struct {
Name string `json:"name"`
StorageType string `json:"storageType"`
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
Bucket string `json:"bucket"`
Region string `json:"region"`
Domain string `json:"domain"`
IsActive int `json:"isActive"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
// 获取现有配置
existingConfig, err := repositories.GetOSSConfigByID(id)
if err != nil || existingConfig == nil {
utils.Error(c, 404, "OSS config not found")
return
}
// 更新字段
if req.Name != "" {
existingConfig.Name = req.Name
}
if req.StorageType != "" {
existingConfig.StorageType = req.StorageType
}
if req.AccessKey != "" && req.AccessKey != "***" {
encryptedAccessKey, err := utils.EncryptAES(req.AccessKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt access key")
return
}
existingConfig.AccessKey = encryptedAccessKey
}
if req.SecretKey != "" && req.SecretKey != "***" {
encryptedSecretKey, err := utils.EncryptAES(req.SecretKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt secret key")
return
}
existingConfig.SecretKey = encryptedSecretKey
}
if req.Bucket != "" {
existingConfig.Bucket = req.Bucket
}
if req.Region != "" {
existingConfig.Region = req.Region
}
if req.Domain != "" {
existingConfig.Domain = req.Domain
}
existingConfig.IsActive = req.IsActive
if err := repositories.UpdateOSSConfig(existingConfig); err != nil {
utils.ServerError(c, err)
return
}
// 不返回加密的密钥
existingConfig.AccessKey = "***"
existingConfig.SecretKey = "***"
utils.SuccessWithMsg(c, "OSS config updated successfully", existingConfig)
}
// AdminDeleteOSSConfig 删除OSS配置
func AdminDeleteOSSConfig(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := strconv.ParseUint(idStr, 10, 32); err != nil {
utils.Error(c, 400, "Invalid OSS config ID")
return
}
if err := repositories.DeleteOSSConfig(id); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "OSS config deleted successfully", nil)
}