Files
hldrCenter/server/main.go
2025-10-04 20:25:05 +08:00

161 lines
4.3 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 main
import (
"fmt"
"net/http"
"strings"
"time"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"github.com/gin-gonic/gin"
)
// 配置常量
const (
allowImageTypes = "image/jpeg,image/png,image/gif,image/webp" // 允许的图片类型
maxFileSize = 5 << 20 // 最大上传文件大小5MB
)
// 阿里云 OSS 配置(请替换为你自己的信息)
const (
OSS_ENDPOINT = "https://oss-cn-shenzhen.aliyuncs.com" // 你的OSS地域节点
OSS_BUCKET_NAME = "hldr-data" // 你的Bucket名称
OSS_ACCESS_KEY_ID = "LTAI5tMTSfbaaAtYBS2gFkf9" // 你的AccessKeyId
OSS_ACCESS_KEY_SECRET = "dHfxH4XziDO0C8ppN94kbLUREAw1Dc" // 你的AccessKeySecret
OSS_OBJECT_PREFIX = "article/" // OSS中的文件前缀类似文件夹
)
func main() {
// 1. 初始化 Gin 引擎
r := gin.Default()
// 2. 配置跨域
r.Use(corsMiddleware())
// 3. 图片上传接口
r.POST("/api/upload/image", uploadImageHandler)
r.POST("/api/upload/cover", func(c *gin.Context) {
// 直接复用已有的上传逻辑
uploadImageHandler(c)
})
// 4. 启动服务
fmt.Println("后端服务启动成功地址http://localhost:8080")
if err := r.Run(":8080"); err != nil {
fmt.Printf("服务启动失败:%v\n", err)
}
}
// corsMiddleware 跨域中间件
func corsMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "http://localhost:5173")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Accept")
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
// 处理 OPTIONS 预检请求
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(http.StatusOK)
return
}
c.Next()
}
}
// uploadImageHandler 图片上传到阿里云OSS处理函数
func uploadImageHandler(c *gin.Context) {
// 获取上传的图片文件
fileHeader, err := c.FormFile("image")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": "获取图片失败,请重新上传",
"error": err.Error(),
})
return
}
// 打开文件
file, err := fileHeader.Open()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"code": 500,
"message": "打开图片文件失败",
"error": err.Error(),
})
return
}
defer file.Close()
// 检查文件大小
if fileHeader.Size > maxFileSize {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": fmt.Sprintf("图片大小不能超过 %dMB", maxFileSize>>20),
})
return
}
// 检查文件类型
fileType := fileHeader.Header.Get("Content-Type")
if !strings.Contains(allowImageTypes, fileType) {
c.JSON(http.StatusBadRequest, gin.H{
"code": 400,
"message": fmt.Sprintf("不支持的图片类型,仅允许:%s", allowImageTypes),
})
return
}
// 初始化OSS客户端
client, err := oss.New(OSS_ENDPOINT, OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"code": 500,
"message": "初始化OSS客户端失败",
"error": err.Error(),
})
return
}
// 获取Bucket
bucket, err := client.Bucket(OSS_BUCKET_NAME)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"code": 500,
"message": "获取Bucket失败",
"error": err.Error(),
})
return
}
// 生成唯一文件名
timestamp := time.Now().Format("20060102150405")
filename := fmt.Sprintf("%s_%s", timestamp, fileHeader.Filename)
objectKey := OSS_OBJECT_PREFIX + filename // OSS中的完整对象键
// 上传文件到OSS
err = bucket.PutObject(objectKey, file)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"code": 500,
"message": "上传图片到OSS失败",
"error": err.Error(),
})
return
}
// 生成图片访问URL
// 注意需要确保Bucket设置了公共读权限或者生成带签名的URL
host := strings.TrimPrefix(OSS_ENDPOINT, "https://")
imageURL := fmt.Sprintf("https://%s.%s/%s", OSS_BUCKET_NAME, host, objectKey)
// 返回成功响应
c.JSON(http.StatusOK, gin.H{
"code": 200,
"message": "图片上传成功",
"data": gin.H{"url": imageURL},
})
}