feat: 优化配置和文件上传
- 上传文件名添加唯一ID避免覆盖 - 支持通过环境变量配置 JWT 密钥和 Token 过期时间 - 支持通过环境变量覆盖管理员账号(可选)
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -260,6 +261,50 @@ func Load() {
|
||||
if cleanedColl := os.Getenv("MONGO_CLEANED_COLLECTION"); cleanedColl != "" {
|
||||
Global.MongoCleanedCollection = cleanedColl
|
||||
}
|
||||
// 认证相关环境变量覆盖
|
||||
if jwtSecret := os.Getenv("JWT_SECRET"); jwtSecret != "" {
|
||||
Global.JWTSecret = jwtSecret
|
||||
}
|
||||
if tokenExpiry := os.Getenv("TOKEN_EXPIRY"); tokenExpiry != "" {
|
||||
if expiry, err := strconv.Atoi(tokenExpiry); err == nil && expiry > 0 {
|
||||
Global.TokenExpiry = expiry
|
||||
}
|
||||
}
|
||||
// 管理员账号环境变量覆盖(覆盖配置文件中的第一个用户)
|
||||
adminUser := os.Getenv("ADMIN_USERNAME")
|
||||
adminPass := os.Getenv("ADMIN_PASSWORD")
|
||||
if adminUser != "" && adminPass != "" {
|
||||
adminName := os.Getenv("ADMIN_NAME")
|
||||
if adminName == "" {
|
||||
adminName = "管理员"
|
||||
}
|
||||
adminEmail := os.Getenv("ADMIN_EMAIL")
|
||||
if adminEmail == "" {
|
||||
adminEmail = adminUser + "@billai.com"
|
||||
}
|
||||
// 查找并更新 admin 用户,或添加新用户
|
||||
found := false
|
||||
for i := range Global.Users {
|
||||
if Global.Users[i].Username == adminUser || Global.Users[i].Role == "admin" {
|
||||
Global.Users[i].Username = adminUser
|
||||
Global.Users[i].Password = adminPass
|
||||
Global.Users[i].Name = adminName
|
||||
Global.Users[i].Email = adminEmail
|
||||
Global.Users[i].Role = "admin"
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
Global.Users = append(Global.Users, UserInfo{
|
||||
Username: adminUser,
|
||||
Password: adminPass,
|
||||
Name: adminName,
|
||||
Email: adminEmail,
|
||||
Role: "admin",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ResolvePath 解析路径(相对路径转为绝对路径)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -52,9 +54,16 @@ func Upload(c *gin.Context) {
|
||||
}
|
||||
billType := req.Type
|
||||
|
||||
// 3. 保存上传的文件
|
||||
// 3. 保存上传的文件(添加唯一ID避免覆盖)
|
||||
timestamp := time.Now().Format("20060102_150405")
|
||||
inputFileName := fmt.Sprintf("%s_%s", timestamp, header.Filename)
|
||||
uniqueID := generateShortID()
|
||||
|
||||
// 获取文件扩展名和基础名
|
||||
ext := filepath.Ext(header.Filename)
|
||||
baseName := header.Filename[:len(header.Filename)-len(ext)]
|
||||
|
||||
// 文件名格式: 时间戳_唯一ID_原始文件名
|
||||
inputFileName := fmt.Sprintf("%s_%s_%s%s", timestamp, uniqueID, baseName, ext)
|
||||
uploadDirAbs := config.ResolvePath(config.Global.UploadDir)
|
||||
inputPath := filepath.Join(uploadDirAbs, inputFileName)
|
||||
|
||||
@@ -182,3 +191,13 @@ func generateFileSequence(dir, timestamp, billType, ext string) string {
|
||||
}
|
||||
return fmt.Sprintf("%03d", len(matches)+1)
|
||||
}
|
||||
|
||||
// generateShortID 生成 6 位随机唯一标识符
|
||||
func generateShortID() string {
|
||||
bytes := make([]byte, 3) // 3 字节 = 6 个十六进制字符
|
||||
if _, err := rand.Read(bytes); err != nil {
|
||||
// 如果随机数生成失败,使用时间纳秒作为备选
|
||||
return fmt.Sprintf("%06x", time.Now().UnixNano()%0xFFFFFF)
|
||||
}
|
||||
return hex.EncodeToString(bytes)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user