Parcourir la source

出本完成,还有一些功能待做

MokiBox il y a 1 an
commit
4d2beea32f
7 fichiers modifiés avec 768 ajouts et 0 suppressions
  1. 8 0
      .idea/.gitignore
  2. 8 0
      go.mod
  3. 11 0
      go.sum
  4. 24 0
      main.go
  5. 86 0
      src/auth.go
  6. 443 0
      src/httpHandles.go
  7. 188 0
      src/units.go

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 8 - 0
go.mod

@@ -0,0 +1,8 @@
+module httpServer
+
+go 1.20
+
+require (
+	github.com/sirupsen/logrus v1.9.3 // indirect
+	golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
+)

+ 11 - 0
go.sum

@@ -0,0 +1,11 @@
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 24 - 0
main.go

@@ -0,0 +1,24 @@
+package main
+
+import (
+	"fmt"
+	"httpServer/src"
+	"net/http"
+)
+
+func main() {
+	mux := http.NewServeMux()
+	mux.HandleFunc("/download/", src.HandleDownloadRequest)
+	mux.HandleFunc("/delete", src.HandleRemoveRequest)
+	mux.HandleFunc("/query", src.HandleQueryRequest)
+	mux.HandleFunc("/upload", src.HandleUploadRequest)
+	mux.HandleFunc("/createDir", src.HandleMkdirRequest)
+	mux.HandleFunc("/base", src.HandleBaseRequest)
+	mux.Handle("/", http.FileServer(http.Dir("D:\\Project\\vue\\http-server\\dist")))
+	mux.HandleFunc("/setCookie", src.HandleLoginRequest)
+	fmt.Println("Server listening on port 8800...")
+	if err := http.ListenAndServe(":8800", mux); err != nil {
+		fmt.Println(err)
+	}
+
+}

+ 86 - 0
src/auth.go

@@ -0,0 +1,86 @@
+package src
+
+import (
+	"errors"
+	"github.com/sirupsen/logrus"
+	"net/http"
+	"os"
+	"strconv"
+	"sync"
+	"time"
+)
+
+// 认证密钥
+var authCode = os.Getenv("AUTH_CODE")
+
+var (
+	sessionStore   = make(map[string]time.Time)
+	pathMd5Store   = make(map[string]string)
+	mu             sync.Mutex
+	sessionTimeout = 30 * time.Minute // Session 超时时间设置为30分钟
+)
+
+// 验证cookie中密钥是否正取
+func authToCookie(cookie *http.Cookie) error {
+	mu.Lock()
+	if authCode == "" {
+		defer mu.Unlock()
+		logrus.Warning("cookie验证, 验证密码未设置!")
+		return nil
+	}
+	if cookie == nil {
+		logrus.Error("cookie验证, cookie为空!")
+		return errors.New("未验证, 请先进行验证! ")
+	}
+	defer mu.Unlock()
+	sessionId := cookie.Value
+	sessionTime := sessionStore[sessionId]
+	// 判断是否过期
+	if sessionTime.Add(sessionTimeout).Before(time.Now()) {
+		delete(sessionStore, sessionId)
+		logrus.Error("cookie验证, session已经过期!")
+		return errors.New("验证已过期, 请重新验证! ")
+	}
+	logrus.Error("cookie验证, 验证通过!")
+	return nil
+}
+
+// 验证密码并下发cookie
+func authToCode(valAuthCode string, now time.Time) (*http.Cookie, error) {
+	mu.Lock()
+	if authCode == "" {
+		defer mu.Unlock()
+		logrus.Warning("密码验证, 验证密码未设置!")
+		return nil, nil
+	}
+	if valAuthCode == generateHash(authCode, -1) {
+		id := generateSessionID()
+		sessionStore[id] = now
+		cookie := &http.Cookie{
+			Name:  "session_id",
+			Value: id,
+		}
+		pathMd5 := generateHash(authCode+strconv.FormatInt(now.Unix(), 10), 8)
+		defer mu.Unlock()
+		pathMd5Store[pathMd5] = "saved"
+		logrus.Info("密码验证, 验证已通过! ")
+		return cookie, nil
+	}
+	logrus.Error("密码验证, 验证密码错误!")
+	return nil, errors.New("验证密码错误! ")
+}
+
+// 验证路径中的码
+func authToPath(pathCode string) (bool, string) {
+	if authCode == "" {
+		logrus.Warning("路径验证, 验证密码未设置!")
+		return true, ""
+	}
+	_, exists := pathMd5Store[pathCode]
+	if exists {
+		logrus.Info("路径验证, 验证通过!")
+		return true, "验证通过! "
+	}
+	logrus.Error("路径验证, 密码过期或者被篡改过!")
+	return false, "验证密码被篡改或过期! "
+}

+ 443 - 0
src/httpHandles.go

@@ -0,0 +1,443 @@
+package src
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/sirupsen/logrus"
+	"io"
+	"mime/multipart"
+	"net/http"
+	"os"
+	"path"
+	"path/filepath"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+)
+
+var (
+	dir         = os.Getenv("FILE_PATH")               // 文件根路径
+	title       = os.Getenv("TITLE")                   // 标题
+	isUpload    = os.Getenv("IS_UPDATE") == "true"     // 是否开启上传
+	isDelete    = os.Getenv("IS_DELETE") == "true"     // 是否开启删除
+	isMkdir     = os.Getenv("IS_MKDIR") == "true"      // 是否开启创建文件夹
+	showHidden  = os.Getenv("SHOW_HIDDEN") == ""       // 是否默认显示隐藏文件
+	showDirSize = os.Getenv("SHOW_DIR_SIZE") == "true" // 是否默认计算文件夹大小
+)
+
+// HandleBaseRequest 处理基本查询
+func HandleBaseRequest(w http.ResponseWriter, r *http.Request) {
+	// 验证
+	cookie, err := r.Cookie("session_id")
+	err = authToCookie(cookie)
+	if err != nil {
+		_, err = w.Write(resultError(-3, err))
+		if err != nil {
+			logrus.Error("基本查询发生异常,异常为: ", err.Error())
+		}
+		return
+	}
+
+	// 组织返回数据
+	resultData := make(map[string]any)
+	if title == "" {
+		title = "HTTP文件服务器"
+	}
+	resultData["title"] = title
+	resultData["isUpload"] = isUpload
+	resultData["isDelete"] = isDelete
+	resultData["isMkdir"] = isMkdir
+	resultData["showHidden"] = showHidden
+	resultData["showDirSize"] = showDirSize
+
+	// 返回基础设置数据
+	_, err = w.Write(resultSuccess(resultData))
+	if err != nil {
+		logrus.Error("基本查询发生异常,异常为: ", err.Error())
+	}
+	logrus.Info("基本查询方法执行成功!")
+}
+
+// HandleLoginRequest 处理登录
+func HandleLoginRequest(w http.ResponseWriter, r *http.Request) {
+	// 获取参数
+	query := r.URL.Query()
+	password := query.Get("password")
+	now := time.Now()
+
+	// 验证
+	cookie, err := authToCode(password, now)
+	if err != nil {
+		_, err = w.Write(resultError(-3, err))
+		if err != nil {
+			logrus.Error("登录发生异常,异常为: ", err.Error())
+		}
+		return
+	}
+
+	// 写入cookie
+	http.SetCookie(w, cookie)
+	_, err = w.Write(resultSuccess(now.Unix()))
+	if err != nil {
+		logrus.Error("登录发生异常,异常为: ", err.Error())
+	}
+	logrus.Error("登录方法执行成功!")
+}
+
+// HandleQueryRequest 查询文件
+func HandleQueryRequest(w http.ResponseWriter, r *http.Request) {
+	// 验证
+	cookie, err := r.Cookie("session_id")
+	err = authToCookie(cookie)
+	if err != nil {
+		_, err = w.Write(resultError(-3, err))
+		if err != nil {
+			logrus.Error("文件查询发生异常, 异常为: ", err.Error())
+		}
+		return
+	}
+
+	// 获取参数, 初始化目录
+	localDir := dir
+	query := r.URL.Query()
+	filePath := query.Get("filePath")
+	localDir = filepath.Join(localDir, filePath)
+	showHidden, _ = strconv.ParseBool(query.Get("showHidden"))   // 是否显示隐藏文件
+	showDirSize, _ = strconv.ParseBool(query.Get("showDirSize")) // 是否计算文件夹大小
+
+	// 打开目录
+	d, err := os.Open(localDir)
+	if err != nil {
+		logrus.Error("文件查询发生异常, 异常为: ", err.Error())
+		_, err = w.Write(resultError(-3, err))
+		if err != nil {
+			logrus.Error("文件查询发生异常, 异常为: ", err.Error())
+		}
+		return
+	}
+	defer func(d *os.File) {
+		err := d.Close()
+		if err != nil {
+
+		}
+	}(d)
+
+	// 读取当前目录下的文件和子目录
+	files, fileErr := d.ReadDir(0)
+	if fileErr != nil {
+		fmt.Println("读取文件异常:", fileErr)
+		_, err := w.Write(resultError(-3, fileErr))
+		if err != nil {
+			return
+		}
+		return
+	}
+
+	// 组织返回的json
+	var filesList []map[string]string
+	for _, file := range files {
+		info, err := file.Info()
+		if err != nil {
+			return
+		}
+		if !showHidden && len(info.Name()) > 0 && info.Name()[0] == '.' {
+			continue
+		}
+		files := make(map[string]string)
+		files["path"] = filePath
+		files["name"] = info.Name()
+		files["fileType"] = ""
+		fileNameSplit := strings.Split(info.Name(), ".")
+		if len(fileNameSplit) > 1 {
+			files["fileType"] = fileNameSplit[len(fileNameSplit)-1]
+		}
+		files["size"] = formatSize(float64(info.Size()), 0)
+		files["modified"] = info.ModTime().Format("2006-01-02 15:04:05")
+		files["type"] = "file"
+		if info.IsDir() {
+			files["fileType"] = "folder"
+			dirPath := filepath.Join(dir, file.Name())
+			files["type"] = "dir"
+			files["size"] = ""
+			if showDirSize {
+				size, err := dirSize(dirPath)
+				if err != nil {
+					fmt.Println("计算目录大小异常:", err)
+				}
+				files["size"] = formatSize(float64(size), 0)
+			}
+		}
+		filesList = append(filesList, files)
+		sort.Slice(filesList, func(i, j int) bool {
+			return filesList[j]["type"] == "file"
+		})
+	}
+
+	// 设置 Content-Type 为 application/json
+	w.Header().Set("Content-Type", "application/json")
+
+	// 返回 JSON 数据
+	_, err = w.Write(resultSuccess(filesList))
+	if err != nil {
+		return
+	}
+}
+
+// HandleDownloadRequest 下载文件
+func HandleDownloadRequest(w http.ResponseWriter, r *http.Request) {
+	query := r.URL.Path
+	reqPthSplit := strings.Split(strings.TrimLeft(query, "/"), "/")
+	fileName := reqPthSplit[len(reqPthSplit)-1]
+	reName := strings.ReplaceAll(fileName, "pkgDir_", "")
+	if reName == ".zip" {
+		reName = "root.zip"
+	}
+	w.Header().Set("Content-Disposition", "attachment; filename="+reName)
+
+	// 认证
+	authCode := reqPthSplit[1]
+	var pathList []string
+	tag, msg := authToPath(authCode)
+	// 第一个元素是url,最后一个是文件名
+	pathList = append(reqPthSplit[2 : len(reqPthSplit)-1])
+	if msg != "" {
+		fmt.Println(msg)
+		if !tag {
+			http.Error(w, msg, 500)
+			return
+		}
+		// 第二个元素是auth
+		pathList = append(reqPthSplit[2 : len(reqPthSplit)-1])
+	}
+
+	filePath := path.Join(pathList...)
+	// 处理文件夹的情况
+	if strings.HasPrefix(fileName, "pkgDir_") {
+		fileName = strings.ReplaceAll(fileName, "pkgDir_", "")
+		dirPath := path.Join(dir, filePath, strings.ReplaceAll(fileName, ".zip", ""))
+		if fileName == ".zip" {
+			fileName = "root" + fileName
+		}
+		createZipDir(dirPath, fileName)
+		defer func(name string) {
+			err := os.Remove(name)
+			if err != nil {
+
+			}
+		}(fileName)
+
+		// 打开 zip 文件
+		file, err := os.Open(fileName)
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+		defer func(file *os.File) {
+			err := file.Close()
+			if err != nil {
+
+			}
+		}(file)
+
+		// 设置响应头
+		w.Header().Set("Content-Type", "application/zip")
+
+		// 将 zip 文件内容复制到响应体中
+		_, err = io.Copy(w, file)
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+		return
+	}
+
+	// 加载文件
+	downloadFile := filepath.Join(dir, filePath, fileName)
+	w.Header().Set("Content-Type", "application/octet-stream")
+	http.ServeFile(w, r, downloadFile)
+}
+
+// HandleRemoveRequest 删除文件
+func HandleRemoveRequest(w http.ResponseWriter, r *http.Request) {
+	cookie, err := r.Cookie("session_id")
+	// 认证
+	authErr := authToCookie(cookie)
+	if authErr != nil {
+		fmt.Println(authErr)
+		_, err := w.Write(resultError(-3, authErr))
+		if err != nil {
+			return
+		}
+		return
+	}
+	// 功能是否开启
+	if !isDelete {
+		w.Header().Set("Content-Type", "application/json")
+		_, err := w.Write(resultError(-2, errors.New("功能未开启! ")))
+		if err != nil {
+			return
+		}
+		return
+	}
+
+	// 初始化目录,获取参数
+	dir := dir
+	query := r.URL.Query()
+
+	// 获取文件路径
+	filePath := query.Get("filePath")
+
+	// 获取文件名
+	fileName := query.Get("fileName")
+
+	// 尝试删除文件
+	err = os.Remove(path.Join(dir, filePath, fileName))
+	if err != nil {
+		fmt.Println("删除文件异常:", err)
+		_, err := w.Write(resultError(-1, err))
+		if err != nil {
+			return
+		}
+		return
+	}
+	fmt.Println("删除成功!")
+
+	// 设置 Content-Type 为 application/json
+	w.Header().Set("Content-Type", "application/json")
+
+	// 返回 JSON 数据
+	_, err = w.Write(resultSuccess(nil))
+}
+
+// HandleUploadRequest 上传文件
+func HandleUploadRequest(w http.ResponseWriter, r *http.Request) {
+	cookie, err := r.Cookie("session_id")
+	// 获取cookie
+	if cookie == nil {
+		_, err = w.Write(resultError(-3, errors.New("未验证, 请先进行验证! ")))
+		if err != nil {
+			return
+		}
+		return
+	}
+	// 认证
+	authErr := authToCookie(cookie)
+	if authErr != nil {
+		fmt.Println(authErr)
+		_, err := w.Write(resultError(-3, authErr))
+		if err != nil {
+			return
+		}
+		return
+	}
+	// 功能是否开启
+	if !isUpload {
+		w.Header().Set("Content-Type", "application/json")
+		_, err := w.Write(resultError(-2, errors.New("功能未开启! ")))
+		if err != nil {
+			return
+		}
+		return
+	}
+	if r.Method == "POST" {
+		// 解析表单数据
+		err := r.ParseMultipartForm(10 << 20) // 最大10MB
+		if err != nil {
+			fmt.Println(err)
+			return
+		}
+		filePath := r.FormValue("filePath")
+
+		// 获取文件句柄和文件头信息
+		file, handler, err := r.FormFile("file")
+		if err != nil {
+			fmt.Println("Error Retrieving the File")
+			fmt.Println(err)
+			return
+		}
+		defer func(file multipart.File) {
+			err := file.Close()
+			if err != nil {
+
+			}
+		}(file)
+
+		fmt.Printf("Uploaded File: %+v\n", handler.Filename)
+		fmt.Printf("File Size: %+v\n", handler.Size)
+		fmt.Printf("MIME Header: %+v\n", handler.Header)
+
+		// 创建目标文件
+		uploadFileName := filepath.Join(dir, filePath, handler.Filename)
+		destFile, err := os.Create(uploadFileName)
+		if err != nil {
+			fmt.Println(err)
+			return
+		}
+		defer func(destFile *os.File) {
+			err := destFile.Close()
+			if err != nil {
+
+			}
+		}(destFile)
+
+		//将文件内容拷贝到目标文件
+		_, err = io.Copy(destFile, file)
+		if err != nil {
+			fmt.Println(err)
+			return
+		}
+
+	}
+}
+
+// HandleMkdirRequest 创建文件夹
+func HandleMkdirRequest(w http.ResponseWriter, r *http.Request) {
+	cookie, err := r.Cookie("session_id")
+	// 获取cookie
+	if cookie == nil {
+		_, err := w.Write(resultError(-3, errors.New("未验证, 请先进行验证! ")))
+		if err != nil {
+			return
+		}
+		return
+	}
+	// 认证
+	authErr := authToCookie(cookie)
+	if authErr != nil {
+		fmt.Println(authErr)
+		_, err := w.Write(resultError(-3, authErr))
+		if err != nil {
+			return
+		}
+		return
+	}
+	// 判断功能是否开启
+	if !isMkdir {
+		w.Header().Set("Content-Type", "application/json")
+		_, err := w.Write(resultError(-2, errors.New("功能未开启! ")))
+		if err != nil {
+			fmt.Println("出现异常: ", err)
+		}
+		return
+	}
+	result := make(map[string]string)
+	query := r.URL.Query()
+	dirPath := query.Get("dirPath")
+	// 创建目录
+	mkdir := path.Join(dir, dirPath)
+	err = os.Mkdir(mkdir, 0755)
+	if err != nil {
+		fmt.Println("Error creating directory:", err)
+		return
+	}
+	result["code"] = "1"
+	// 设置 Content-Type 为 application/json
+	w.Header().Set("Content-Type", "application/json")
+
+	resultJson, err := json.Marshal(result)
+
+	// 返回 JSON 数据
+	_, err = w.Write(resultJson)
+}

+ 188 - 0
src/units.go

@@ -0,0 +1,188 @@
+package src
+
+import (
+	"archive/zip"
+	"crypto/md5"
+	"crypto/rand"
+	"encoding/base64"
+	"encoding/hex"
+	"encoding/json"
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+)
+
+// 格式化文件大小
+func formatSize(size float64, unit int) string {
+	// 递归得出size的单位
+	if int(size)/1024 != 0 {
+		unit := unit + 1
+		return formatSize(size/1024, unit)
+	}
+	// 将数字进行处理
+	num := handleNum(size)
+	// 添加单位并返回
+	if unit == 0 {
+		return num + "B"
+	} else if unit == 1 {
+		return num + "KB"
+	} else if unit == 2 {
+		return num + "MB"
+	} else if unit == 3 {
+		return num + "GB"
+	} else if unit == 4 {
+		return num + "TB"
+	}
+	return num + "?B"
+}
+
+// 处理数字
+func handleNum(num float64) string {
+	// 如果没有小数位 直接返回整数位即可
+	if int(num*100)%100 == 0 {
+		return strconv.Itoa(int(num))
+	}
+	return fmt.Sprintf("%.2f", num)
+}
+
+// 计算文件大小
+func dirSize(dir string) (int64, error) {
+	var size int64
+	// 遍历文件夹下的所有文件和子文件夹
+	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
+		if err != nil {
+			return err
+		}
+		// 如果是文件,则累加文件大小
+		if !info.IsDir() {
+			size += info.Size()
+		}
+		return nil
+	})
+	if err != nil {
+		return 0, err
+	}
+	return size, nil
+}
+
+// 生成hash
+func generateHash(str string, genLen int) string {
+	data := []byte(str)
+	var hash []byte
+	h := md5.New()
+	h.Write(data)
+	hash = h.Sum(nil)
+	if genLen != -1 {
+		return hex.EncodeToString(hash)[:genLen]
+	}
+	return hex.EncodeToString(hash)
+}
+
+// 生成sessionId
+func generateSessionID() string {
+	// 创建一个32字节的随机字节数组
+	b := make([]byte, 32)
+	_, err := rand.Read(b)
+	if err != nil {
+		fmt.Println("sessionId生成异常! ", err)
+		return ""
+	}
+	// 将随机字节数组编码为URL安全的Base64字符串
+	return base64.URLEncoding.EncodeToString(b)
+}
+
+// 创建目录压缩
+func createZipDir(dir, zipFile string) {
+	// 创建一个新的 zip 文件
+	newZipFile, err := os.Create(zipFile)
+	if err != nil {
+		fmt.Println("文件创建失败!", err)
+		return
+	}
+	defer func(newZipFile *os.File) {
+		err := newZipFile.Close()
+		if err != nil {
+			fmt.Println("zip创建异常: ", err)
+		}
+	}(newZipFile)
+
+	// 创建一个 zip.Writer
+	zipWriter := zip.NewWriter(newZipFile)
+	defer func(zipWriter *zip.Writer) {
+		err := zipWriter.Close()
+		if err != nil {
+			fmt.Println("zip写对象创建异常: ", err)
+		}
+	}(zipWriter)
+
+	// 遍历目录中的所有文件和子目录
+	err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
+		if err != nil {
+			return err
+		}
+
+		// 将文件或目录添加到 zip 文件中
+		if !info.IsDir() {
+			file, err := os.Open(path)
+			if err != nil {
+				return err
+			}
+			defer func(file *os.File) {
+				err := file.Close()
+				if err != nil {
+
+				}
+			}(file)
+
+			// 创建 zip 文件中的文件
+			zipPath := strings.TrimPrefix(strings.ReplaceAll(path, "\\", "/"), dir+"/")
+			if zipPath == "" {
+				return nil
+			}
+			zipPath = filepath.ToSlash(zipPath)
+			f, err := zipWriter.Create(zipPath)
+			if err != nil {
+				return err
+			}
+
+			// 将文件内容复制到 zip 文件中
+			_, err = io.Copy(f, file)
+			if err != nil {
+				return err
+			}
+		}
+		return nil
+	})
+	if err != nil {
+		return
+	}
+}
+
+// 返回数据
+func resultError(code int, err error) []byte {
+	return resultAll("操作失败!", code, nil, err)
+}
+
+func resultSuccess(data any) []byte {
+	return resultAll("操作成功!", 1, data, nil)
+}
+
+func resultAll(msg string, code int, data any, err error) []byte {
+	result := make(map[string]any)
+	result["code"] = code
+	result["msg"] = msg
+	if data != nil {
+		result["data"] = data
+	}
+	if err != nil {
+		result["err"] = err.Error()
+	}
+	marshal, err := json.Marshal(result)
+	if err != nil {
+		fmt.Println("json转换错误!")
+	}
+	return marshal
+}