460 lines
11 KiB
Go
460 lines
11 KiB
Go
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)
|
||
}
|