更新前后端代码
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ClientIP 获取客户端真实IP
|
||||
func ClientIP(c *gin.Context) string {
|
||||
// 优先取反向代理头
|
||||
for _, header := range []string{"X-Real-IP", "X-Forwarded-For"} {
|
||||
if v := c.GetHeader(header); v != "" {
|
||||
ips := strings.Split(v, ",")
|
||||
ip := strings.TrimSpace(ips[0])
|
||||
if ip != "" {
|
||||
return ip
|
||||
}
|
||||
}
|
||||
}
|
||||
return c.ClientIP()
|
||||
}
|
||||
|
||||
// SanitizePath 清理虚拟路径,防止路径穿越
|
||||
func SanitizePath(p string) string {
|
||||
p = strings.ReplaceAll(p, "\\", "/")
|
||||
parts := make([]string, 0, 8)
|
||||
for _, seg := range strings.Split(p, "/") {
|
||||
seg = strings.TrimSpace(seg)
|
||||
if seg == "" || seg == "." {
|
||||
continue
|
||||
}
|
||||
if seg == ".." {
|
||||
if len(parts) > 0 {
|
||||
parts = parts[:len(parts)-1]
|
||||
}
|
||||
continue
|
||||
}
|
||||
parts = append(parts, seg)
|
||||
}
|
||||
return strings.Join(parts, "/")
|
||||
}
|
||||
|
||||
// IsValidPassword 检查密码强度:至少8位,包含字母和数字
|
||||
func IsValidPassword(pwd string) bool {
|
||||
if len(pwd) < 8 {
|
||||
return false
|
||||
}
|
||||
hasLetter, hasDigit := false, false
|
||||
for _, ch := range pwd {
|
||||
switch {
|
||||
case ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z':
|
||||
hasLetter = true
|
||||
case ch >= '0' && ch <= '9':
|
||||
hasDigit = true
|
||||
}
|
||||
}
|
||||
return hasLetter && hasDigit
|
||||
}
|
||||
|
||||
// IsEmail 简单校验邮箱格式
|
||||
func IsEmail(s string) bool {
|
||||
at := strings.IndexByte(s, '@')
|
||||
if at <= 0 || at == len(s)-1 {
|
||||
return false
|
||||
}
|
||||
domain := s[at+1:]
|
||||
return strings.Contains(domain, ".") && strings.IndexByte(domain, '.') != 0 && strings.IndexByte(domain, '.') != len(domain)-1
|
||||
}
|
||||
|
||||
// HumanSize 将字节数转为可读大小
|
||||
func HumanSize(n int64) string {
|
||||
const unit = 1024
|
||||
if n < unit {
|
||||
return itoa(n) + " B"
|
||||
}
|
||||
div, exp := int64(unit), 0
|
||||
for m := n / unit; m >= unit && exp < 4; m /= unit {
|
||||
div *= unit
|
||||
exp++
|
||||
}
|
||||
val := float64(n) / float64(div)
|
||||
s := trimFloat(val)
|
||||
units := []string{"KB", "MB", "GB", "TB", "PB"}
|
||||
return s + " " + units[exp]
|
||||
}
|
||||
|
||||
func itoa(n int64) string {
|
||||
if n == 0 {
|
||||
return "0"
|
||||
}
|
||||
neg := n < 0
|
||||
if neg {
|
||||
n = -n
|
||||
}
|
||||
var buf [20]byte
|
||||
i := len(buf)
|
||||
for n > 0 {
|
||||
i--
|
||||
buf[i] = byte('0' + n%10)
|
||||
n /= 10
|
||||
}
|
||||
if neg {
|
||||
i--
|
||||
buf[i] = '-'
|
||||
}
|
||||
return string(buf[i:])
|
||||
}
|
||||
|
||||
func trimFloat(f float64) string {
|
||||
// 保留两位小数并去掉末尾多余的0
|
||||
s := itoa(int64(f))
|
||||
frac := f - float64(int64(f))
|
||||
if frac < 0.005 {
|
||||
return s
|
||||
}
|
||||
d1 := int64(frac * 10)
|
||||
if d1 > 9 {
|
||||
d1 = 9
|
||||
}
|
||||
frac = frac*10 - float64(d1)
|
||||
d2 := int64(frac * 10)
|
||||
if d2 > 9 {
|
||||
d2 = 9
|
||||
}
|
||||
if d2 < 5 {
|
||||
if d1 == 0 {
|
||||
return s
|
||||
}
|
||||
return s + "." + itoa(d1)
|
||||
}
|
||||
return s + "." + itoa(d1) + itoa(d2)
|
||||
}
|
||||
Reference in New Issue
Block a user