fonchain-fiee/pkg/utils/untils.go
2025-02-19 14:24:15 +08:00

460 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 utils
import (
"archive/zip"
"bytes"
"crypto/md5"
"crypto/sha256"
"dubbo.apache.org/dubbo-go/v3/common/logger"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"time"
"github.com/fonchain_enterprise/fonchain-main/pkg/e"
"github.com/gin-gonic/gin"
"github.com/tealeg/xlsx"
"go.uber.org/zap"
"unsafe"
)
const (
ExcelPrefix = "xlsx"
)
// ToString 转string
func ToString(value interface{}) string {
switch v := value.(type) {
case string:
return v
case int:
return strconv.FormatInt(int64(v), 10)
case int8:
return strconv.FormatInt(int64(v), 10)
case int16:
return strconv.FormatInt(int64(v), 10)
case int32:
return strconv.FormatInt(int64(v), 10)
case int64:
return strconv.FormatInt(v, 10)
case uint:
return strconv.FormatUint(uint64(v), 10)
case uint8:
return strconv.FormatUint(uint64(v), 10)
case uint16:
return strconv.FormatUint(uint64(v), 10)
case uint32:
return strconv.FormatUint(uint64(v), 10)
case uint64:
return strconv.FormatUint(v, 10)
}
return ""
}
// Contains 是否包含
func Contains[T comparable](elems []T, elem T) bool {
for _, e := range elems {
if elem == e {
return true
}
}
return false
}
// CheckTruth 检测字符串是不是真
func CheckTruth(vals ...string) bool {
for _, val := range vals {
if val != "" && !strings.EqualFold(val, "false") {
return true
}
}
return false
}
func CheckDirPath(path string, create bool) (exists bool, err error) {
exists = false
if path == "" {
err = errors.New(e.GetMsg(e.InvalidParams))
return
}
if _, err = os.Stat(path); os.IsNotExist(err) {
if !create {
return
}
if err = os.MkdirAll(path, os.ModePerm); err != nil {
return
}
}
exists = true
return
}
func ToExcel(titleList []string, dataList []interface{}, dataType string) (content io.ReadSeeker) {
// 生成一个新的文件
file := xlsx.NewFile()
// 添加sheet页
sheet, _ := file.AddSheet("Sheet1")
// 插入表头
titleRow := sheet.AddRow()
for _, v := range titleList {
cell := titleRow.AddCell()
cell.Value = v
}
// 插入内容
for _, v := range dataList {
row := sheet.AddRow()
if dataType == "struct" {
row.WriteStruct(v, -1)
} else if dataType == "slice" {
row.WriteSlice(v, -1)
}
}
var buffer bytes.Buffer
_ = file.Write(&buffer)
content = bytes.NewReader(buffer.Bytes())
return
}
// ToExcelByType 转成Excel类型
func ToExcelByType(titleList []string, dataList []interface{}, dataType string, filePath string) (content io.ReadSeeker, err error) {
// 生成一个新的文件
file := xlsx.NewFile()
// 添加sheet页
sheet, _ := file.AddSheet("Sheet1")
// 插入表头
titleRow := sheet.AddRow()
for _, v := range titleList {
cell := titleRow.AddCell()
cell.Value = v
}
// 插入内容
for _, v := range dataList {
row := sheet.AddRow()
if dataType == "struct" {
row.WriteStruct(v, -1)
} else if dataType == "slice" {
row.WriteSlice(v, -1)
}
}
var buffer bytes.Buffer
_ = file.Write(&buffer)
if filePath != "" {
if err = file.Save(filePath); err != nil {
return
}
} else {
content = bytes.NewReader(buffer.Bytes())
}
return
}
// ResponseXls content 为上面生成的io.ReadSeeker fileTag 为返回前端的文件名
func ResponseXls(c *gin.Context, content io.ReadSeeker, fileTag string) {
fileName := fmt.Sprintf("%s.%s", fileTag, ExcelPrefix)
c.Writer.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName))
c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
http.ServeContent(c.Writer, c.Request, fileName, time.Now(), content)
}
func SHA256V(str []byte) string {
h := sha256.New()
h.Write(str)
return hex.EncodeToString(h.Sum(nil))
}
func GenerateSHA256Hash(path string) (string, error) {
b, err := os.ReadFile(path)
if err != nil {
zap.L().Error("GenerateSHA256Hash err", zap.Error(err))
return "", err
}
return SHA256V(b), nil
}
// SimpleStructField 将结构体转成 map kv
func SimpleStructField(v interface{}) (data map[string]interface{}, err error) {
data = map[string]interface{}{}
dataType := reflect.TypeOf(v)
dataValue := reflect.ValueOf(v)
if dataType.Kind() == reflect.Ptr {
if dataValue.IsNil() {
logger.Errorf("dataValue.IsNil")
err = errors.New(e.GetMsg(e.Error))
}
// 如果是指针则要判断一下是否为struct
originType := reflect.ValueOf(v).Elem().Type()
if originType.Kind() != reflect.Struct {
logger.Errorf("dataValue.Kind")
err = errors.New(e.GetMsg(e.Error))
return
}
// 解引用
dataValue = dataValue.Elem()
dataType = dataType.Elem()
} else {
logger.Errorf("non ptr")
err = errors.New(e.GetMsg(e.Error))
return
}
num := dataType.NumField()
for i := 0; i < num; i++ {
field := dataType.Field(i)
fieldName := field.Name
fieldValue := dataValue.FieldByName(fieldName)
if !fieldValue.IsValid() {
continue
}
if fieldValue.CanInterface() {
data[fieldName] = fieldValue.Interface()
if fieldValue.CanSet() && fieldValue.Kind() == reflect.String {
oldValue := fieldValue.Interface().(string)
fieldValue.SetString(oldValue)
}
} else {
// 强行取址
forceValue := reflect.NewAt(fieldValue.Type(), unsafe.Pointer(fieldValue.UnsafeAddr())).Elem()
data[fieldName] = forceValue
}
}
return
}
// CreateDirPath 递归创建文件夹
func CreateDirPath(path string) (err error) {
if _, err = os.Stat(path); os.IsNotExist(err) {
if err = os.MkdirAll(path, os.ModePerm); err != nil {
return
}
}
return
}
// SaveUrlFileDisk 保存图片到本地
func SaveUrlFileDisk(url string, path string, filename string) (fullPath string, err error) {
if err = CreateDirPath(path); err != nil {
zap.L().Error("SaveUrlFileDisk err ", zap.Error(err))
return
}
if filename == "" {
stepName := strings.Split(url, "/")
if len(stepName) > 1 {
filename = stepName[len(stepName)-1]
}
}
resp, err := http.Get(url)
if err != nil {
logger.Errorf("SaveUrlFileDisk get err", err)
err = errors.New(e.GetMsg(e.ERROR_DOWNLOAD_FILE))
return
}
defer func() {
if err := recover(); err != nil {
logger.Errorf("SaveUrlFileDisk close err", err)
}
resp.Body.Close()
}()
bytes, err := ioutil.ReadAll(resp.Body)
fullPath = fmt.Sprintf("%s/%s", path, filename)
// 写入数据
err = ioutil.WriteFile(fullPath, bytes, 0777)
return
}
// Unzip 解压zip
func Unzip(zipFilePath string, destDir string) error {
zipReader, err := zip.OpenReader(zipFilePath)
if err != nil {
return err
}
defer zipReader.Close()
var decodeName string
for _, f := range zipReader.File {
if f.Flags == 0 {
//如果标致位是0 则是默认的本地编码 默认为gbk
i := bytes.NewReader([]byte(f.Name))
decoder := transform.NewReader(i, simplifiedchinese.GB18030.NewDecoder())
content, _ := ioutil.ReadAll(decoder)
decodeName = string(content)
} else {
//如果标志为是 1 << 11也就是 2048 则是utf-8编码
decodeName = f.Name
}
fpath := filepath.Join(destDir, decodeName)
if f.FileInfo().IsDir() {
_ = os.MkdirAll(fpath, os.ModePerm)
} else {
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return err
}
inFile, errS := f.Open()
if errS != nil {
return errS
}
defer inFile.Close()
outFile, errA := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if errA != nil {
return errA
}
defer outFile.Close()
_, err = io.Copy(outFile, inFile)
if err != nil {
return err
}
}
}
return nil
}
// ZipFile 打包成zip文件
// @title ZipDir
// @description 将文件夹下的文件打包成zip
// @auth dyb 时间
// @param src string 文件夹路径
// @return err error 错误内容
func ZipFile(srcDir string, zipFilePath string) (err error) {
// 预防:旧文件无法覆盖
os.RemoveAll(zipFilePath)
// 创建zip文件
zipfile, _ := os.Create(zipFilePath)
defer zipfile.Close()
// 打开zip文件
archive := zip.NewWriter(zipfile)
defer archive.Close()
// 遍历路径信息
filepath.Walk(srcDir, func(path string, info os.FileInfo, _ error) error {
// 如果是源路径,提前进行下一个遍历
if path == srcDir {
return nil
}
// 获取:文件头信息
header, _ := zip.FileInfoHeader(info)
header.Name = strings.TrimPrefix(path, srcDir+`\`)
header.Name = strings.Replace(path, srcDir, "", 1)
if header.Name[:1] == "\\" || header.Name[:1] == "/" {
header.Name = header.Name[1:]
}
// 判断:文件是不是文件夹
if info.IsDir() {
header.Name += `/`
} else {
// 设置zip的文件压缩算法
header.Method = zip.Deflate
}
// 创建:压缩包头部信息
writer, _ := archive.CreateHeader(header)
if !info.IsDir() {
file, _ := os.Open(path)
defer file.Close()
io.Copy(writer, file)
}
return nil
})
return
}
// PostForm 发送post请求
func PostForm(urlStr string, data url.Values) (string, error) {
resp, err := http.PostForm(urlStr, data)
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
// handle error
}
return string(body), err
}
func PostBody(url string, data interface{}) (httpCode int, respBody string, err error) {
var payload []byte
payload, err = json.Marshal(data)
if err != nil {
zap.L().Error("PostBody Marshal", zap.Error(err))
err = errors.New(e.GetMsg(e.JsonUnmarshal))
return
}
// 创建一个请求
req, err := http.NewRequest("POST", url, bytes.NewBuffer(payload))
if err != nil {
zap.L().Error("NewRequest err", zap.Error(err))
err = errors.New(e.GetMsg(e.ErrorHttp))
return
}
// 设置请求头
req.Header.Set("Content-Type", "application/json")
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
zap.L().Error("client.Do err", zap.Error(err))
err = errors.New(e.GetMsg(e.ErrorHttp))
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
zap.L().Error("ReadAll err", zap.Error(err))
err = errors.New(e.GetMsg(e.ErrorBody))
return
}
httpCode = resp.StatusCode
respBody = string(body)
return
}
func Get(url string) string {
client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Get(url)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var buffer [512]byte
result := bytes.NewBuffer(nil)
for {
n, err := resp.Body.Read(buffer[0:])
result.Write(buffer[0:n])
if err != nil && err == io.EOF {
break
} else if err != nil {
panic(err)
}
}
return result.String()
}
func StructToMap(obj interface{}) map[string]interface{} {
objMap := make(map[string]interface{})
objVal := reflect.ValueOf(obj)
for i := 0; i < objVal.NumField(); i++ {
field := objVal.Type().Field(i)
value := objVal.Field(i).Interface()
objMap[field.Name] = value
}
return objMap
}
func Md5Str(input string) string {
hashNew := md5.New()
hashNew.Write([]byte(input))
hashBytes := hashNew.Sum(nil)
return hex.EncodeToString(hashBytes)
}