Merge branch 'develop' into develop
This commit is contained in:
@@ -14,6 +14,12 @@ import (
|
||||
const breakpointDir = "./breakpointDir/"
|
||||
const finishDir = "./fileDir/"
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: BreakPointContinue
|
||||
//@description: 断点续传
|
||||
//@param: content []byte, fileName string, contentNumber int, contentTotal int, fileMd5 string
|
||||
//@return: error, string
|
||||
|
||||
func BreakPointContinue(content []byte, fileName string, contentNumber int, contentTotal int, fileMd5 string) (error, string) {
|
||||
path := breakpointDir + fileMd5 + "/"
|
||||
err := os.MkdirAll(path, os.ModePerm)
|
||||
@@ -25,6 +31,12 @@ func BreakPointContinue(content []byte, fileName string, contentNumber int, cont
|
||||
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: CheckMd5
|
||||
//@description: 检查Md5
|
||||
//@param: content []byte, chunkMd5 string
|
||||
//@return: CanUpload bool
|
||||
|
||||
func CheckMd5(content []byte, chunkMd5 string) (CanUpload bool) {
|
||||
fileMd5 := MD5V(content)
|
||||
if fileMd5 == chunkMd5 {
|
||||
@@ -34,6 +46,12 @@ func CheckMd5(content []byte, chunkMd5 string) (CanUpload bool) {
|
||||
}
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: makeFileContent
|
||||
//@description: 创建切片内容
|
||||
//@param: content []byte, fileName string, FileDir string, contentNumber int
|
||||
//@return: error, string
|
||||
|
||||
func makeFileContent(content []byte, fileName string, FileDir string, contentNumber int) (error, string) {
|
||||
path := FileDir + fileName + "_" + strconv.Itoa(contentNumber)
|
||||
f, err := os.Create(path)
|
||||
@@ -49,6 +67,12 @@ func makeFileContent(content []byte, fileName string, FileDir string, contentNum
|
||||
return nil, path
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: makeFileContent
|
||||
//@description: 创建切片文件
|
||||
//@param: fileName string, FileMd5 string
|
||||
//@return: error, string
|
||||
|
||||
func MakeFile(fileName string, FileMd5 string) (error, string) {
|
||||
rd, err := ioutil.ReadDir(breakpointDir + FileMd5)
|
||||
if err != nil {
|
||||
@@ -72,6 +96,12 @@ func MakeFile(fileName string, FileMd5 string) (error, string) {
|
||||
return nil, finishDir + fileName
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: RemoveChunk
|
||||
//@description: 移除切片
|
||||
//@param: FileMd5 string
|
||||
//@return: error
|
||||
|
||||
func RemoveChunk(FileMd5 string) error {
|
||||
err := os.RemoveAll(breakpointDir + FileMd5)
|
||||
return err
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@interface_name: RunTask
|
||||
//@description: Task接口
|
||||
|
||||
type RunTask interface {
|
||||
AddTask()
|
||||
RunTask()
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@struct_name: T
|
||||
//@description: Task任务
|
||||
|
||||
type T struct {
|
||||
sync.Mutex
|
||||
|
||||
// 获取事件channel
|
||||
ch chan struct{}
|
||||
|
||||
closeChan chan struct{}
|
||||
|
||||
// 记录process对象
|
||||
p *os.Process
|
||||
|
||||
// 执行任务
|
||||
f func(chan struct{}) error
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: NewT
|
||||
//@description: T的实例化方法
|
||||
//@return: *T
|
||||
|
||||
func NewT() *T {
|
||||
return newT(nil)
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: newT
|
||||
//@description:
|
||||
//@param: f func(chan struct{}) error
|
||||
//@return: *T
|
||||
|
||||
func newT(f func(chan struct{}) error) *T {
|
||||
t := &T{
|
||||
Mutex: sync.Mutex{},
|
||||
ch: make(chan struct{}, 1),
|
||||
closeChan: make(chan struct{}),
|
||||
f: f,
|
||||
}
|
||||
if f == nil {
|
||||
t.f = t.DefaultF
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: *T
|
||||
//@function: AddTask
|
||||
//@description: 添加任务
|
||||
|
||||
func (t *T) AddTask() {
|
||||
if len(t.ch) == 1 {
|
||||
return
|
||||
}
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
if len(t.ch) == 1 {
|
||||
// 代表已经有任务了
|
||||
// 直接丢弃这次任务
|
||||
return
|
||||
}
|
||||
t.ch <- struct{}{}
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: *T
|
||||
//@function: RunTask
|
||||
//@description: 启动任务
|
||||
|
||||
func (t *T) RunTask() {
|
||||
fmt.Println("进入")
|
||||
// 这里做的make 是用于关闭上一个执行的任务
|
||||
ch := make(chan struct{})
|
||||
// 先run服务
|
||||
go t.f(ch)
|
||||
for {
|
||||
_, ok := <-t.ch
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
ch <- struct{}{}
|
||||
// 等待上一个关闭
|
||||
<-t.closeChan
|
||||
go t.f(ch)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: t *T
|
||||
//@function: DefaultF
|
||||
//@description: 默认的StartFunction
|
||||
//@param: ch chan struct{}
|
||||
//@return: error
|
||||
|
||||
func (t *T) DefaultF(ch chan struct{}) error {
|
||||
var buildCmd *exec.Cmd
|
||||
var cmd *exec.Cmd
|
||||
|
||||
// 检测系统是否有编译环境
|
||||
_, err := exec.LookPath("go")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// build
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
buildCmd = exec.Command("go", "build", "-o", "server.exe", "main.go")
|
||||
default:
|
||||
buildCmd = exec.Command("go", "build", "-o", "server", "main.go")
|
||||
}
|
||||
//cmd = exec.Command("go", "run", "main.go")
|
||||
err = buildCmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("build 执行完成")
|
||||
// 执行
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
cmd = exec.Command("server.exe")
|
||||
default:
|
||||
cmd = exec.Command("./server")
|
||||
}
|
||||
|
||||
// 开始执行任务
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
err = t.echo(cmd, ctx)
|
||||
<-ch
|
||||
// 回收资源
|
||||
fmt.Println("pid:", t.p.Pid, "->Kill")
|
||||
err = t.p.Kill()
|
||||
cancel()
|
||||
// 发送关闭完成信号
|
||||
t.closeChan <- struct{}{}
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: t *T
|
||||
//@function: echo
|
||||
//@description: 封装回显
|
||||
//@param: cmd *exec.Cmd, ctx context.Context
|
||||
//@return: error
|
||||
|
||||
func (t *T) echo(cmd *exec.Cmd, ctx context.Context) error {
|
||||
var stdoutBuf bytes.Buffer
|
||||
stdoutIn, _ := cmd.StdoutPipe()
|
||||
var errStdout error
|
||||
stdout := io.MultiWriter(os.Stdout, &stdoutBuf)
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func(ctx context.Context) {
|
||||
_, errStdout = io.Copy(stdout, stdoutIn)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
}
|
||||
}(ctx)
|
||||
t.p = cmd.Process
|
||||
fmt.Println("pid", t.p.Pid)
|
||||
go func() {
|
||||
_ = cmd.Wait()
|
||||
if errStdout != nil {
|
||||
fmt.Printf("failed to capture stdout or stderr\n")
|
||||
}
|
||||
fmt.Printf("%s\n", string(stdoutBuf.Bytes()))
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
//_ = os.Stdout.Close()
|
||||
return
|
||||
default:
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@struct_name: Watch
|
||||
//@description: 监控对象
|
||||
|
||||
type Watch struct {
|
||||
*fsnotify.Watcher
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: NewWatch
|
||||
//@description: Watch的实例化方法
|
||||
//@return: *Watch
|
||||
|
||||
func NewWatch() *Watch {
|
||||
obj, _ := fsnotify.NewWatcher()
|
||||
return &Watch{obj}
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: w *Watch
|
||||
//@function: Watch
|
||||
//@description: 监控对象
|
||||
//@param: path string, t *T
|
||||
//@return: error
|
||||
|
||||
func (w *Watch) Watch(path string, t *T) error {
|
||||
// 先转化为绝对路径
|
||||
path, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 判断是单个文件还是目录文件
|
||||
fileInfo, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 判断是否是目录 添加监控
|
||||
if fileInfo.IsDir() {
|
||||
// dir
|
||||
err = w.watchDir(path)
|
||||
|
||||
} else {
|
||||
err = w.watchFile(path)
|
||||
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c := make(chan error)
|
||||
// 启动监控
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case even, ok := <-w.Events:
|
||||
if !ok {
|
||||
// close
|
||||
fmt.Println("Errors close")
|
||||
c <- errors.New("errors close")
|
||||
return
|
||||
}
|
||||
// 判断事件
|
||||
switch {
|
||||
case even.Op&fsnotify.Create == fsnotify.Create:
|
||||
//这里获取新创建文件的信息,如果是目录,则加入监控中
|
||||
fmt.Println("创建文件 : ", even.Name)
|
||||
//t.AddTask()
|
||||
_ = w.Add(even.Name)
|
||||
case even.Op&fsnotify.Write == fsnotify.Write:
|
||||
fmt.Println("修改文件 : ", even.Name)
|
||||
w.addTask(t, even.Name)
|
||||
case even.Op&fsnotify.Remove == fsnotify.Remove || even.Op&fsnotify.Rename == fsnotify.Rename:
|
||||
fmt.Println("删除或重命名文件 : ", even.Name)
|
||||
_ = w.Remove(even.Name)
|
||||
w.addTask(t, even.Name)
|
||||
}
|
||||
case err = <-w.Errors:
|
||||
fmt.Println("even Error:", err)
|
||||
c <- err
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return <-c
|
||||
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: w *Watch
|
||||
//@function: watchDir
|
||||
//@description: 处理监控目录
|
||||
//@param: path string
|
||||
//@return: error
|
||||
|
||||
func (w *Watch) watchDir(path string) error {
|
||||
// 先将自己添加到监控
|
||||
err := w.Add(path)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileSlice, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, f := range fileSlice {
|
||||
fPath := filepath.Join(path, f.Name())
|
||||
if !f.IsDir() {
|
||||
// 判断是否可监控的文件
|
||||
if chickPower(fPath) {
|
||||
err = w.watchFile(fPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := w.watchDir(fPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: w *Watch
|
||||
//@function: watchDir
|
||||
//@description: 处理监控单文件
|
||||
//@param: path string
|
||||
//@return: error
|
||||
|
||||
func (w *Watch) watchFile(path string) error {
|
||||
var err error
|
||||
if chickPower(path) {
|
||||
err = w.Add(path)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: chickPower
|
||||
//@description: 判断是否在可控范围内
|
||||
//@param: path string
|
||||
//@return: error
|
||||
|
||||
func chickPower(name string) bool {
|
||||
name = filepath.Ext(name)
|
||||
return name == ".go" || name == ".yaml"
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@object: w *Watch
|
||||
//@function: addTask
|
||||
//@description: 偏函数 简化发送任务
|
||||
//@param: path string
|
||||
//@return: error
|
||||
|
||||
func (w *Watch) addTask(t *T, name string) {
|
||||
if chickPower(name) {
|
||||
fmt.Println("Add Task->>>>>>")
|
||||
t.AddTask()
|
||||
}
|
||||
}
|
||||
+10
-10
@@ -6,11 +6,11 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// @title PathExists
|
||||
// @description 文件目录是否存在
|
||||
// @auth (2020/04/05 20:22)
|
||||
// @param path string
|
||||
// @return err error
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: PathExists
|
||||
//@description: 文件目录是否存在
|
||||
//@param: path string
|
||||
//@return: bool, error
|
||||
|
||||
func PathExists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
@@ -23,11 +23,11 @@ func PathExists(path string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// @title createDir
|
||||
// @description 批量创建文件夹
|
||||
// @auth (2020/04/05 20:22)
|
||||
// @param dirs string
|
||||
// @return err error
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: CreateDir
|
||||
//@description: 批量创建文件夹
|
||||
//@param: dirs ...string
|
||||
//@return: err error
|
||||
|
||||
func CreateDir(dirs ...string) (err error) {
|
||||
for _, v := range dirs {
|
||||
|
||||
+24
-1
@@ -11,12 +11,23 @@ import (
|
||||
"github.com/jordan-wright/email"
|
||||
)
|
||||
|
||||
//@author: [maplepie](https://github.com/maplepie)
|
||||
//@function: Email
|
||||
//@description: Email发送方法
|
||||
//@param: subject string, body string
|
||||
//@return: error
|
||||
|
||||
func Email(subject string, body string) error {
|
||||
to := strings.Split(global.GVA_CONFIG.Email.To, ",")
|
||||
return send(to, subject, body)
|
||||
}
|
||||
|
||||
// ErrorToEmail Error 发送邮件
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: ErrorToEmail
|
||||
//@description: 给email中间件错误发送邮件到指定邮箱
|
||||
//@param: subject string, body string
|
||||
//@return: error
|
||||
|
||||
func ErrorToEmail(subject string, body string) error {
|
||||
to := strings.Split(global.GVA_CONFIG.Email.To, ",")
|
||||
if to[len(to)-1] == "" { // 判断切片的最后一个元素是否为空,为空则移除
|
||||
@@ -25,11 +36,23 @@ func ErrorToEmail(subject string, body string) error {
|
||||
return send(to, subject, body)
|
||||
}
|
||||
|
||||
//@author: [maplepie](https://github.com/maplepie)
|
||||
//@function: EmailTest
|
||||
//@description: Email测试方法
|
||||
//@param: subject string, body string
|
||||
//@return: error
|
||||
|
||||
func EmailTest(subject string, body string) error {
|
||||
to := []string{global.GVA_CONFIG.Email.From}
|
||||
return send(to, subject, body)
|
||||
}
|
||||
|
||||
//@author: [maplepie](https://github.com/maplepie)
|
||||
//@function: send
|
||||
//@description: Email发送方法
|
||||
//@param: subject string, body string
|
||||
//@return: error
|
||||
|
||||
func send(to []string, subject string, body string) error {
|
||||
from := global.GVA_CONFIG.Email.From
|
||||
nickname := global.GVA_CONFIG.Email.Nickname
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: FileMove
|
||||
//@description: 文件移动供外部调用
|
||||
//@param: src string, dst string(src: 源位置,绝对路径or相对路径, dst: 目标位置,绝对路径or相对路径,必须为文件夹)
|
||||
//@return: err error
|
||||
|
||||
func FileMove(src string, dst string) (err error) {
|
||||
if dst == "" {
|
||||
return nil
|
||||
}
|
||||
src, err = filepath.Abs(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dst, err = filepath.Abs(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var revoke = false
|
||||
dir := filepath.Dir(dst)
|
||||
Redirect:
|
||||
_, err = os.Stat(dir)
|
||||
if err != nil {
|
||||
err = os.MkdirAll(dir, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !revoke {
|
||||
revoke = true
|
||||
goto Redirect
|
||||
}
|
||||
}
|
||||
return os.Rename(src, dst)
|
||||
}
|
||||
@@ -6,7 +6,12 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 利用反射将结构体转化为map
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: StructToMap
|
||||
//@description: 利用反射将结构体转化为map
|
||||
//@param: obj interface{}
|
||||
//@return: map[string]interface{}
|
||||
|
||||
func StructToMap(obj interface{}) map[string]interface{} {
|
||||
obj1 := reflect.TypeOf(obj)
|
||||
obj2 := reflect.ValueOf(obj)
|
||||
@@ -18,7 +23,12 @@ func StructToMap(obj interface{}) map[string]interface{} {
|
||||
return data
|
||||
}
|
||||
|
||||
//将数组格式化为字符串
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: ArrayToString
|
||||
//@description: 将数组格式化为字符串
|
||||
//@param: array []interface{}
|
||||
//@return: string
|
||||
|
||||
func ArrayToString(array []interface{}) string {
|
||||
return strings.Replace(strings.Trim(fmt.Sprint(array), "[]"), " ", ",", -1)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,12 @@ import (
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: MD5V
|
||||
//@description: md5加密
|
||||
//@param: str []byte
|
||||
//@return: string
|
||||
|
||||
func MD5V(str []byte) string {
|
||||
h := md5.New()
|
||||
h.Write(str)
|
||||
|
||||
@@ -11,7 +11,11 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// GetWriteSyncer zap logger中加入file-rotatelogs
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: GetWriteSyncer
|
||||
//@description: zap logger中加入file-rotatelogs
|
||||
//@return: zapcore.WriteSyncer, error
|
||||
|
||||
func GetWriteSyncer() (zapcore.WriteSyncer, error) {
|
||||
fileWriter, err := zaprotatelogs.New(
|
||||
path.Join(global.GVA_CONFIG.Zap.Director, "%Y-%m-%d.log"),
|
||||
|
||||
@@ -9,7 +9,11 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// GetWriteSyncer zap logger中加入file-rotatelogs
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: GetWriteSyncer
|
||||
//@description: zap logger中加入file-rotatelogs
|
||||
//@return: zapcore.WriteSyncer, error
|
||||
|
||||
func GetWriteSyncer() (zapcore.WriteSyncer, error) {
|
||||
fileWriter, err := zaprotatelogs.New(
|
||||
path.Join(global.GVA_CONFIG.Zap.Director, "%Y-%m-%d.log"),
|
||||
|
||||
+20
-4
@@ -50,7 +50,11 @@ type Disk struct {
|
||||
UsedPercent int `json:"usedPercent"`
|
||||
}
|
||||
|
||||
// InitOS OS信息
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: InitCPU
|
||||
//@description: OS信息
|
||||
//@return: o Os, err error
|
||||
|
||||
func InitOS() (o Os) {
|
||||
o.GOOS = runtime.GOOS
|
||||
o.NumCPU = runtime.NumCPU()
|
||||
@@ -60,7 +64,11 @@ func InitOS() (o Os) {
|
||||
return o
|
||||
}
|
||||
|
||||
// InitCPU CPU信息
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: InitCPU
|
||||
//@description: CPU信息
|
||||
//@return: c Cpu, err error
|
||||
|
||||
func InitCPU() (c Cpu, err error) {
|
||||
if cores, err := cpu.Counts(false); err != nil {
|
||||
return c, err
|
||||
@@ -75,7 +83,11 @@ func InitCPU() (c Cpu, err error) {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// InitRAM ARM信息
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: InitRAM
|
||||
//@description: ARM信息
|
||||
//@return: r Rrm, err error
|
||||
|
||||
func InitRAM() (r Rrm, err error) {
|
||||
if u, err := mem.VirtualMemory(); err != nil{
|
||||
return r, err
|
||||
@@ -87,7 +99,11 @@ func InitRAM() (r Rrm, err error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// InitDisk 硬盘信息
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: InitDisk
|
||||
//@description: 硬盘信息
|
||||
//@return: d Disk, err error
|
||||
|
||||
func InitDisk() (d Disk, err error) {
|
||||
if u, err := disk.Usage("/"); err != nil{
|
||||
return d, err
|
||||
|
||||
@@ -14,8 +14,16 @@ import (
|
||||
|
||||
type Local struct{}
|
||||
|
||||
// UploadFile 上传文件
|
||||
func (l Local) UploadFile(file *multipart.FileHeader) (string, string, error) {
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@author: [ccfish86](https://github.com/ccfish86)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@object: *Local
|
||||
//@function: UploadFile
|
||||
//@description: 上传文件
|
||||
//@param: file *multipart.FileHeader
|
||||
//@return: string, string, error
|
||||
|
||||
func (*Local) UploadFile(file *multipart.FileHeader) (string, string, error) {
|
||||
// 读取文件后缀
|
||||
ext := path.Ext(file.Filename)
|
||||
// 读取文件名并加密
|
||||
@@ -55,8 +63,16 @@ func (l Local) UploadFile(file *multipart.FileHeader) (string, string, error) {
|
||||
return p, filename, nil
|
||||
}
|
||||
|
||||
// DeleteFile 删除文件
|
||||
func (l Local) DeleteFile(key string) error {
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@author: [ccfish86](https://github.com/ccfish86)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@object: *Local
|
||||
//@function: DeleteFile
|
||||
//@description: 删除文件
|
||||
//@param: key string
|
||||
//@return: error
|
||||
|
||||
func (*Local) DeleteFile(key string) error {
|
||||
p := global.GVA_CONFIG.Local.Path + "/" + key
|
||||
if strings.Contains(p, global.GVA_CONFIG.Local.Path) {
|
||||
if err := os.Remove(p); err != nil {
|
||||
|
||||
@@ -14,7 +14,15 @@ import (
|
||||
|
||||
type Qiniu struct{}
|
||||
|
||||
// Upload 上传文件
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@author: [ccfish86](https://github.com/ccfish86)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@object: *Qiniu
|
||||
//@function: UploadFile
|
||||
//@description: 上传文件
|
||||
//@param: file *multipart.FileHeader
|
||||
//@return: string, string, error
|
||||
|
||||
func (*Qiniu) UploadFile(file *multipart.FileHeader) (string, string, error) {
|
||||
putPolicy := storage.PutPolicy{Scope: global.GVA_CONFIG.Qiniu.Bucket}
|
||||
mac := qbox.NewMac(global.GVA_CONFIG.Qiniu.AccessKey, global.GVA_CONFIG.Qiniu.SecretKey)
|
||||
@@ -39,7 +47,15 @@ func (*Qiniu) UploadFile(file *multipart.FileHeader) (string, string, error) {
|
||||
return global.GVA_CONFIG.Qiniu.ImgPath + "/" + ret.Key, ret.Key, nil
|
||||
}
|
||||
|
||||
// DeleteFile 删除文件
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@author: [ccfish86](https://github.com/ccfish86)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@object: *Qiniu
|
||||
//@function: DeleteFile
|
||||
//@description: 删除文件
|
||||
//@param: key string
|
||||
//@return: error
|
||||
|
||||
func (*Qiniu) DeleteFile(key string) error {
|
||||
mac := qbox.NewMac(global.GVA_CONFIG.Qiniu.AccessKey, global.GVA_CONFIG.Qiniu.SecretKey)
|
||||
cfg := qiniuConfig()
|
||||
@@ -51,7 +67,13 @@ func (*Qiniu) DeleteFile(key string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// config 根据配置文件进行返回七牛云的配置
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@object: *Qiniu
|
||||
//@function: qiniuConfig
|
||||
//@description: 根据配置文件进行返回七牛云的配置
|
||||
//@param: key string
|
||||
//@return: error
|
||||
|
||||
func qiniuConfig() *storage.Config {
|
||||
cfg := storage.Config{
|
||||
UseHTTPS: global.GVA_CONFIG.Qiniu.UseHTTPS,
|
||||
|
||||
@@ -5,13 +5,23 @@ import (
|
||||
"mime/multipart"
|
||||
)
|
||||
|
||||
var Oss OSS
|
||||
//@author: [ccfish86](https://github.com/ccfish86)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@interface_name: OSS
|
||||
//@description: OSS接口
|
||||
|
||||
type OSS interface {
|
||||
UploadFile(file *multipart.FileHeader) (string, string, error)
|
||||
DeleteFile(key string) error
|
||||
}
|
||||
|
||||
//@author: [ccfish86](https://github.com/ccfish86)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: NewOss
|
||||
//@description: OSS接口
|
||||
//@description: OSS的实例化方法
|
||||
//@return: OSS
|
||||
|
||||
func NewOss() OSS {
|
||||
switch global.GVA_CONFIG.System.OssType {
|
||||
case "local":
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"go.uber.org/zap"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func UploadFileLocal(file *multipart.FileHeader) (err error, localPath string, key string) {
|
||||
// 读取文件后缀
|
||||
ext := path.Ext(file.Filename)
|
||||
// 读取文件名并加密
|
||||
fileName := strings.TrimSuffix(file.Filename, ext)
|
||||
fileName = MD5V([]byte(fileName))
|
||||
// 拼接新文件名
|
||||
lastName := fileName + "_" + time.Now().Format("20060102150405") + ext
|
||||
// 读取全局变量的定义路径
|
||||
savePath := global.GVA_CONFIG.Local.Path
|
||||
// 尝试创建此路径
|
||||
err = os.MkdirAll(savePath, os.ModePerm)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("upload local file fail:", zap.Any("err", err))
|
||||
return err, "", ""
|
||||
}
|
||||
// 拼接路径和文件名
|
||||
dst := savePath + "/" + lastName
|
||||
// 下面为上传逻辑
|
||||
// 打开文件 defer 关闭
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("upload local file fail:", zap.Any("err", err))
|
||||
return err, "", ""
|
||||
}
|
||||
defer src.Close()
|
||||
// 创建文件 defer 关闭
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("upload local file fail:", zap.Any("err", err))
|
||||
return err, "", ""
|
||||
}
|
||||
defer out.Close()
|
||||
// 传输(拷贝)文件
|
||||
_, err = io.Copy(out, src)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("upload local file fail:", zap.Any("err", err))
|
||||
return err, "", ""
|
||||
}
|
||||
return nil, dst, lastName
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"gin-vue-admin/global"
|
||||
"github.com/qiniu/api.v7/v7/auth/qbox"
|
||||
"github.com/qiniu/api.v7/v7/storage"
|
||||
"go.uber.org/zap"
|
||||
"mime/multipart"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 接收两个参数 一个文件流 一个 bucket 你的七牛云标准空间的名字
|
||||
func UploadRemote(file *multipart.FileHeader) (err error, path string, key string) {
|
||||
putPolicy := storage.PutPolicy{
|
||||
Scope: global.GVA_CONFIG.Qiniu.Bucket,
|
||||
}
|
||||
mac := qbox.NewMac(global.GVA_CONFIG.Qiniu.AccessKey, global.GVA_CONFIG.Qiniu.SecretKey)
|
||||
upToken := putPolicy.UploadToken(mac)
|
||||
cfg := storage.Config{}
|
||||
// 空间对应的机房
|
||||
cfg.Zone = &storage.ZoneHuadong
|
||||
// 是否使用https域名
|
||||
cfg.UseHTTPS = false
|
||||
// 上传是否使用CDN上传加速
|
||||
cfg.UseCdnDomains = false
|
||||
formUploader := storage.NewFormUploader(&cfg)
|
||||
ret := storage.PutRet{}
|
||||
putExtra := storage.PutExtra{
|
||||
Params: map[string]string{
|
||||
"x:name": "github logo",
|
||||
},
|
||||
}
|
||||
f, e := file.Open()
|
||||
if e != nil {
|
||||
fmt.Println(e)
|
||||
return e, "", ""
|
||||
}
|
||||
dataLen := file.Size
|
||||
fileKey := fmt.Sprintf("%d%s", time.Now().Unix(), file.Filename) // 文件名格式 自己可以改 建议保证唯一性
|
||||
err = formUploader.Put(context.Background(), &ret, upToken, fileKey, f, dataLen, &putExtra)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("upload file fail:", zap.Any("err", err))
|
||||
return err, "", ""
|
||||
}
|
||||
return err, global.GVA_CONFIG.Qiniu.ImgPath + "/" + ret.Key, ret.Key
|
||||
}
|
||||
|
||||
func DeleteFile(key string) error {
|
||||
|
||||
mac := qbox.NewMac(global.GVA_CONFIG.Qiniu.AccessKey, global.GVA_CONFIG.Qiniu.SecretKey)
|
||||
cfg := storage.Config{
|
||||
// 是否使用https域名进行资源管理
|
||||
UseHTTPS: false,
|
||||
}
|
||||
// 指定空间所在的区域,如果不指定将自动探测
|
||||
// 如果没有特殊需求,默认不需要指定
|
||||
// cfg.Zone=&storage.ZoneHuabei
|
||||
bucketManager := storage.NewBucketManager(mac, &cfg)
|
||||
err := bucketManager.Delete(global.GVA_CONFIG.Qiniu.Bucket, key)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+73
-11
@@ -13,7 +13,12 @@ type RulesMap map[string]Rules
|
||||
|
||||
var CustomizeMap = make(map[string]Rules)
|
||||
|
||||
// 注册自定义规则方案建议在路由初始化层即注册
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: RegisterRule
|
||||
//@description: 注册自定义规则方案建议在路由初始化层即注册
|
||||
//@param: key string, rule Rules
|
||||
//@return: err error
|
||||
|
||||
func RegisterRule(key string, rule Rules) (err error) {
|
||||
if CustomizeMap[key] != nil {
|
||||
return errors.New(key + "已注册,无法重复注册")
|
||||
@@ -23,42 +28,83 @@ func RegisterRule(key string, rule Rules) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// 非空 不能为其对应类型的0值
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: NotEmpty
|
||||
//@description: 非空 不能为其对应类型的0值
|
||||
//@param: key string, rule Rules
|
||||
//@return: err error
|
||||
|
||||
func NotEmpty() string {
|
||||
return "notEmpty"
|
||||
}
|
||||
|
||||
// 小于入参(<) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Lt
|
||||
//@description: 小于入参(<) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
||||
//@param: mark string
|
||||
//@return: string
|
||||
|
||||
func Lt(mark string) string {
|
||||
return "lt=" + mark
|
||||
}
|
||||
|
||||
// 小于等于入参(<=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Le
|
||||
//@description: 小于等于入参(<=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
||||
//@param: mark string
|
||||
//@return: string
|
||||
|
||||
func Le(mark string) string {
|
||||
return "le=" + mark
|
||||
}
|
||||
|
||||
// 等于入参(==) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Eq
|
||||
//@description: 等于入参(==) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
||||
//@param: mark string
|
||||
//@return: string
|
||||
|
||||
func Eq(mark string) string {
|
||||
return "eq=" + mark
|
||||
}
|
||||
|
||||
// 不等于入参(!=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Ne
|
||||
//@description: 不等于入参(!=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
||||
//@param: mark string
|
||||
//@return: string
|
||||
|
||||
func Ne(mark string) string {
|
||||
return "ne=" + mark
|
||||
}
|
||||
|
||||
// 大于等于入参(>=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Ge
|
||||
//@description: 大于等于入参(>=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
||||
//@param: mark string
|
||||
//@return: string
|
||||
|
||||
func Ge(mark string) string {
|
||||
return "ge=" + mark
|
||||
}
|
||||
|
||||
// 大于入参(>) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Gt
|
||||
//@description: 大于入参(>) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
|
||||
//@param: mark string
|
||||
//@return: string
|
||||
|
||||
func Gt(mark string) string {
|
||||
return "gt=" + mark
|
||||
}
|
||||
|
||||
// 校验方法 接收两个参数 入参实例,规则map
|
||||
//
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Verify
|
||||
//@description: 校验方法
|
||||
//@param: st interface{}, roleMap Rules(入参实例,规则map)
|
||||
//@return: err error
|
||||
|
||||
func Verify(st interface{}, roleMap Rules) (err error) {
|
||||
compareMap := map[string]bool{
|
||||
"lt": true,
|
||||
@@ -99,7 +145,12 @@ func Verify(st interface{}, roleMap Rules) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 长度和数字的校验方法 根据类型自动校验
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: compareVerify
|
||||
//@description: 长度和数字的校验方法 根据类型自动校验
|
||||
//@param: value reflect.Value, VerifyStr string
|
||||
//@return: bool
|
||||
|
||||
func compareVerify(value reflect.Value, VerifyStr string) bool {
|
||||
switch value.Kind() {
|
||||
case reflect.String, reflect.Slice, reflect.Array:
|
||||
@@ -115,7 +166,12 @@ func compareVerify(value reflect.Value, VerifyStr string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// 非空校验
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: isBlank
|
||||
//@description: 非空校验
|
||||
//@param: value reflect.Value
|
||||
//@return: bool
|
||||
|
||||
func isBlank(value reflect.Value) bool {
|
||||
switch value.Kind() {
|
||||
case reflect.String:
|
||||
@@ -134,6 +190,12 @@ func isBlank(value reflect.Value) bool {
|
||||
return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface())
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: compare
|
||||
//@description: 比较函数
|
||||
//@param: value interface{}, VerifyStr string
|
||||
//@return: bool
|
||||
|
||||
func compare(value interface{}, VerifyStr string) bool {
|
||||
VerifyStrArr := strings.Split(VerifyStr, "=")
|
||||
val := reflect.ValueOf(value)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package utils
|
||||
|
||||
var (
|
||||
IdVerify = Rules{"ID": {NotEmpty()}}
|
||||
ApiVerify = Rules{"Path": {NotEmpty()}, "Description": {NotEmpty()}, "ApiGroup": {NotEmpty()}, "Method": {NotEmpty()}}
|
||||
MenuVerify = Rules{"Path": {NotEmpty()}, "ParentId": {NotEmpty()}, "Name": {NotEmpty()}, "Component": {NotEmpty()}, "Sort": {Ge("0")}}
|
||||
MenuMetaVerify = Rules{"Title": {NotEmpty()}}
|
||||
LoginVerify = Rules{"CaptchaId": {NotEmpty()}, "Captcha": {NotEmpty()}, "Username": {NotEmpty()}, "Password": {NotEmpty()}}
|
||||
SetUserVerify = Rules{"ID": {NotEmpty()}, "Username": {NotEmpty()}, "NickName": {NotEmpty()}, "HeaderImg": {NotEmpty()}}
|
||||
RegisterVerify = Rules{"Username": {NotEmpty()}, "NickName": {NotEmpty()}, "Password": {NotEmpty()}, "AuthorityId": {NotEmpty()}}
|
||||
PageInfoVerify = Rules{"Page": {NotEmpty()}, "PageSize": {NotEmpty()}}
|
||||
CustomerVerify = Rules{"CustomerName": {NotEmpty()}, "CustomerPhoneData": {NotEmpty()}}
|
||||
AutoCodeVerify = Rules{"Abbreviation": {NotEmpty()}, "StructName": {NotEmpty()}, "PackageName": {NotEmpty()}, "Fields": {NotEmpty()}}
|
||||
WorkFlowVerify = Rules{"WorkflowNickName": {NotEmpty()}, "WorkflowName": {NotEmpty()}, "WorkflowDescription": {NotEmpty()}, "WorkflowStepInfo": {NotEmpty()}}
|
||||
AuthorityVerify = Rules{"AuthorityId": {NotEmpty()}, "AuthorityName": {NotEmpty()}, "ParentId": {NotEmpty()}}
|
||||
AuthorityIdVerify = Rules{"AuthorityId": {NotEmpty()}}
|
||||
OldAuthorityVerify = Rules{"OldAuthorityId": {NotEmpty()}}
|
||||
ChangePasswordVerify = Rules{"Username": {NotEmpty()}, "Password": {NotEmpty()}, "NewPassword": {NotEmpty()}}
|
||||
SetUserAuthorityVerify = Rules{"UUID": {NotEmpty()}, "AuthorityId": {NotEmpty()}}
|
||||
)
|
||||
@@ -7,26 +7,36 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ZipFiles(filename string, files []string, oldform, newform string) error {
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: ZipFiles
|
||||
//@description: 压缩文件
|
||||
//@param: filename string, files []string, oldform, newform string
|
||||
//@return: error
|
||||
|
||||
func ZipFiles(filename string, files []string, oldForm, newForm string) error {
|
||||
|
||||
newZipFile, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer newZipFile.Close()
|
||||
defer func() {
|
||||
_ = newZipFile.Close()
|
||||
}()
|
||||
|
||||
zipWriter := zip.NewWriter(newZipFile)
|
||||
defer zipWriter.Close()
|
||||
defer func() {
|
||||
_ = zipWriter.Close()
|
||||
}()
|
||||
|
||||
// 把files添加到zip中
|
||||
for _, file := range files {
|
||||
|
||||
err = func(file string) error {
|
||||
zipFile, err := os.Open(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zipFile.Close()
|
||||
|
||||
// 获取file的基础信息
|
||||
info, err := zipFile.Stat()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user