Files
easygoadmin/utils/utils.go
yaoyilin bafdda2efd fix: 兼容多图上传控件
兼容多图上传控件
2022-11-10 14:58:01 +08:00

436 lines
9.2 KiB
Go
Raw Permalink 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.

/**
* 系统工具类
* @author
* @since 2021/8/25
* @File : utils
*/
package utils
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"github.com/gogf/gf/container/garray"
"gitlab.52pay.top/go/easygoadmin/library/cfg"
"gitlab.52pay.top/go/easygoadmin/utils/gconv"
"gitlab.52pay.top/go/easygoadmin/utils/gmd5"
"gitlab.52pay.top/go/easygoadmin/utils/gstr"
"log"
"os"
"regexp"
"strconv"
"strings"
"time"
)
// 调试模式
func AppDebug() bool {
// 获取配置实例
config := cfg.Instance()
return config.EasyGoAdmin.Debug
}
// 登录用户ID
func Uid(ctx *gin.Context) int {
// 初始化session对象
session := sessions.Default(ctx)
// 获取用户ID
userId := gconv.Int(session.Get("userId"))
// 返回用户ID
return userId
}
// 判断用户登录状态
func IsLogin(ctx *gin.Context) bool {
// 初始化session对象
session := sessions.Default(ctx)
// 获取用户ID
userId := session.Get("userId")
return userId != nil
}
// 检测用户签名
func CheckSign(ctx *gin.Context) bool {
ctx.Request.ParseForm()
dataMap := make(map[string]string)
sign := ""
appId := ""
//说明:须post方法,加: 'Content-Type': 'application/x-www-form-urlencoded'
for key := range ctx.Request.PostForm {
if key == "sign" {
sign = ctx.PostForm(key)
}
if key == "app_id" {
appId = ctx.PostForm(key)
}
dataMap[key] = ctx.PostForm(key)
}
//
for key := range ctx.Request.URL.Query() {
if key == "sign" {
sign = ctx.Query(key)
}
if key == "app_id" {
appId = ctx.Query(key)
}
dataMap[key] = ctx.Query(key)
}
if len(dataMap) < 0 || sign == "" {
return false
}
keyArray := garray.NewStrArray()
for key := range dataMap {
if key == "sign" {
continue
}
keyArray.Append(key)
}
secret := GetAppSecret(ctx, appId)
if secret == "" {
return false
}
newSign := GetNewSign(dataMap, keyArray, secret)
if newSign != sign {
return false
}
return true
}
// 获取签名
func GetNewSign(dataMap map[string]string, keyArray *garray.StrArray, secret string) string {
keyArray.Sort()
str := ""
keyArray.Iterator(func(k int, v string) bool {
val := dataMap[v]
tmp := fmt.Sprintf("%s=%s", v, val)
if k == 0 {
str = tmp
} else {
str = fmt.Sprintf("%s&%s", str, tmp)
}
return true
})
str = fmt.Sprintf("%s&key=%s", str, secret)
d := []byte(str)
m := md5.New()
m.Write(d)
newSign := hex.EncodeToString(m.Sum(nil))
newSign = strings.ToUpper(newSign)
return newSign
}
type PbSettingAppUtils struct {
Id int `json:"id" xorm:"not null pk autoincr comment('主键ID') INT(10)"`
AppId string `json:"app_id"`
AppName string `json:"app_name"`
Phone string `json:"phone"`
AppKey string `json:"app_key"`
Status int64 `json:"status"`
CouponSmsContent string `json:"coupon_sms_content"`
ServiceAddress string `json:"service_address"`
ComName string `json:"com_name"`
FilingNo string `json:"filing_no"`
}
func (r *PbSettingAppUtils) TableName() string {
return "pb_setting_app"
}
// 根据 appid 获取 appSecret
func GetAppSecret(ctx *gin.Context, appId string) string {
cache := GetRedisHelper()
cacheKey := fmt.Sprintf("Utils:GetAppSecretV2:%s", appId)
val := cache.Get(ctx, cacheKey).Val()
if val != "" {
return val
}
var info PbSettingAppUtils
_, err := XormDb.Where("app_id = ?", appId).Get(&info)
if err != nil {
return ""
}
cache.Set(ctx, cacheKey, info.AppKey, 3*time.Minute)
return info.AppKey
}
// 根据 appid 获取 appSecret
func GetAppInfo(ctx *gin.Context, appId string) PbSettingAppUtils {
cache := GetRedisHelper()
cacheKey := fmt.Sprintf("Utils:GetAppInfo:V2:%s", appId)
val := cache.Get(ctx, cacheKey).Val()
var info PbSettingAppUtils
if val != "" {
json.Unmarshal([]byte(val), &info)
return info
}
_, err := XormDb.Where("app_id = ?", appId).Get(&info)
if err != nil {
return PbSettingAppUtils{}
}
jsonStr, _ := json.Marshal(info)
cache.Set(ctx, cacheKey, jsonStr, 4*time.Minute)
return info
}
// 获取数据库表
func GetDatabase() (string, error) {
config := cfg.Instance()
if config == nil {
fmt.Printf("参数错误")
}
// 获取数据库连接
link := config.Database.Master
if link == "" {
return "", errors.New("数据库配置读取错误")
}
// 分裂字符串
linkArr := strings.Split(link, "/")
return strings.Split(linkArr[1], "?")[0], nil
}
func Md5(password string) (string, error) {
// 第一次MD5加密
password, err := gmd5.Encrypt(password)
if err != nil {
return "", err
}
// 第二次MD5加密
password2, err := gmd5.Encrypt(password)
if err != nil {
return "", err
}
return password2, nil
}
// 数组反转
func Reverse(arr *[]string) {
length := len(*arr)
var temp string
for i := 0; i < length/2; i++ {
temp = (*arr)[i]
(*arr)[i] = (*arr)[length-1-i]
(*arr)[length-1-i] = temp
}
}
// 获取客户端IP
func GetClientIp(ctx *gin.Context) string {
ip := ctx.Request.Header.Get("X-Forwarded-For")
if ip == "" {
ip = ctx.ClientIP()
}
return ip
}
func ImageUrl() string {
// 获取配置实例
config := cfg.Instance()
return config.EasyGoAdmin.Image
}
// 获取文件地址
func GetImageUrl(path string) string {
parts := strings.Split(path, ",")
var urls []string
for _, part := range parts {
urls = append(urls, ImageUrl()+part)
}
return strings.Join(urls, ",")
}
func InStringArray(value string, array []string) bool {
for _, v := range array {
if v == value {
return true
}
}
return false
}
// 判断元素是否在数组中
func InArray(value string, array []interface{}) bool {
for _, v := range array {
if gconv.String(v) == value {
return true
}
}
return false
}
// 附件目录
func UploadPath() string {
// 获取配置实例
config := cfg.Instance()
// 附件存储路径
upload_dir := config.EasyGoAdmin.Uploads
if upload_dir != "" {
return upload_dir
} else {
// 获取项目根目录
curDir, _ := os.Getwd()
return curDir + "/public/uploads"
}
}
// 临时目录
func TempPath() string {
return UploadPath() + "/temp"
}
// 图片存放目录
func ImagePath() string {
return UploadPath() + "/images"
}
// 文件目录(非图片目录)
func FilePath() string {
return UploadPath() + "/file"
}
// 创建文件夹并设置权限
func CreateDir(path string) bool {
// 判断文件夹是否存在
if IsExist(path) {
return true
}
// 创建多层级目录
err2 := os.MkdirAll(path, os.ModePerm)
if err2 != nil {
log.Println(err2)
return false
}
return true
}
// 判断文件/文件夹是否存在(返回true是存在)
func IsExist(path string) bool {
// 读取文件信息,判断文件是否存在
_, err := os.Stat(path)
if err != nil {
log.Println(err)
if os.IsExist(err) {
// 根据错误类型进行判断
return true
}
return false
}
return true
}
func SaveImage(url string, dirname string) (string, error) {
// 判断文件地址是否为空
if gstr.Equal(url, "") {
return "", errors.New("文件地址不能为空")
}
// 判断是否本站图片
if gstr.Contains(url, ImageUrl()) {
// 本站图片
// 是否临时图片
if gstr.Contains(url, "temp") {
// 临时图片
// 创建目录
dirPath := ImagePath() + "/" + dirname + "/" + time.Now().Format("20060102")
if !CreateDir(dirPath) {
return "", errors.New("文件目录创建失败")
}
// 原始图片地址
oldPath := gstr.Replace(url, ImageUrl(), UploadPath())
// 目标目录地址
newPath := ImagePath() + "/" + dirname + gstr.Replace(url, ImageUrl()+"/temp", "")
// 移动文件
os.Rename(oldPath, newPath)
return gstr.Replace(newPath, UploadPath(), ""), nil
} else {
// 非临时图片
path := gstr.Replace(url, ImageUrl(), "")
return path, nil
}
} else {
// 远程图片
// TODO...
}
return "", errors.New("保存文件异常")
}
// 处理富文本
func SaveImageContent(content string, title string, dirname string) string {
str := `<img src="(?s:(.*?))"`
//解析、编译正则
ret := regexp.MustCompile(str)
// 提取图片信息
alls := ret.FindAllStringSubmatch(content, -1)
// 遍历图片数据
for _, v := range alls {
// 获取图片地址
item := v[1]
if item == "" {
continue
}
// 保存图片至正式目录
image, _ := SaveImage(item, dirname)
if image != "" {
content = strings.ReplaceAll(content, item, "[IMG_URL]"+image)
}
}
// 设置ALT标题
if strings.Contains(content, "alt=\"\"") && title != "" {
content = strings.ReplaceAll(content, "alt=\"\"", "alt=\""+title+"\"")
}
return content
}
// 截取字符串,支持多字节字符
// start起始下标负数从从尾部开始最后一个为-1
// length截取长度负数表示截取到末尾
func SubStr(str string, start int, length int) (result string) {
s := []rune(str)
total := len(s)
if total == 0 {
return
}
// 允许从尾部开始计算
if start < 0 {
start = total + start
if start < 0 {
return
}
}
if start > total {
return
}
// 到末尾
if length < 0 {
length = total
}
end := start + length
if end > total {
result = string(s[start:])
} else {
result = string(s[start:end])
}
return
}
func FloatToInt(f float64) int {
i, _ := strconv.Atoi(fmt.Sprintf("%1.0f", f))
return i
}