fonchain-fiee/pkg/utils/untils.go

460 lines
11 KiB
Go
Raw Normal View History

2025-02-19 06:24:15 +00:00
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)
}