Merge branch 'develop' of https://gitee.com/fusenpack/fusenapi into develop
This commit is contained in:
@@ -1,5 +1,24 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
const UploadFileLimitSize = 200 << 20
|
||||
|
||||
// File uploadfile 文件(multipart...)
|
||||
type File struct {
|
||||
Filename string
|
||||
Header map[string][]string
|
||||
Size int64
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// StatusResponse 公司自定义状态码
|
||||
type StatusResponse struct {
|
||||
Code int // 状态码
|
||||
@@ -136,3 +155,75 @@ func (resp *Response) SetStatusAddMessage(sr *StatusResponse, msg string, data .
|
||||
}
|
||||
return newResp
|
||||
}
|
||||
|
||||
var fileType = reflect.TypeOf(File{})
|
||||
|
||||
func RequestFileParse(r *http.Request, req any) error {
|
||||
vreq := reflect.ValueOf(req)
|
||||
if vreq.Kind() != reflect.Ptr {
|
||||
panic("req must &req pass")
|
||||
}
|
||||
|
||||
reqValue := vreq.Elem()
|
||||
reqType := reqValue.Type()
|
||||
for i := 0; i < reqType.NumField(); i++ {
|
||||
if tname, ok := reqType.Field(i).Tag.Lookup("file"); ok {
|
||||
file, fheader, err := r.FormFile(tname)
|
||||
if err != nil {
|
||||
logx.Info("upload file error")
|
||||
return err
|
||||
}
|
||||
|
||||
if fheader.Size > UploadFileLimitSize {
|
||||
err = fmt.Errorf("upload file size over limit %d", UploadFileLimitSize)
|
||||
logx.Info(err)
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
logx.Info("upload file data error")
|
||||
return err
|
||||
}
|
||||
err = file.Close()
|
||||
if err != nil {
|
||||
logx.Info("file close error")
|
||||
return err
|
||||
}
|
||||
|
||||
field := reqValue.Field(i)
|
||||
|
||||
// aa1:
|
||||
// field.Field(0).Set(fheader.Filename)
|
||||
// field.Field(1).Set( fheader.Header)
|
||||
// field.Field(2).Set( fheader.Size)
|
||||
// field.Field(3).Set( data)
|
||||
|
||||
if field.Kind() == reflect.Ptr {
|
||||
if field.IsNil() {
|
||||
fsfile := reflect.New(field.Type().Elem())
|
||||
fsfile = fsfile.Elem()
|
||||
fsfile.Field(0).Set(reflect.ValueOf(fheader.Filename))
|
||||
fsfile.Field(1).Set(reflect.ValueOf(fheader.Header))
|
||||
fsfile.Field(2).Set(reflect.ValueOf(fheader.Size))
|
||||
fsfile.Field(3).Set(reflect.ValueOf(data))
|
||||
field.Set(fsfile.Addr())
|
||||
} else {
|
||||
field = field.Elem()
|
||||
field.Field(0).Set(reflect.ValueOf(fheader.Filename))
|
||||
field.Field(1).Set(reflect.ValueOf(fheader.Header))
|
||||
field.Field(2).Set(reflect.ValueOf(fheader.Size))
|
||||
field.Field(3).Set(reflect.ValueOf(data))
|
||||
}
|
||||
} else {
|
||||
field.Field(0).Set(reflect.ValueOf(fheader.Filename))
|
||||
field.Field(1).Set(reflect.ValueOf(fheader.Header))
|
||||
field.Field(2).Set(reflect.ValueOf(fheader.Size))
|
||||
field.Field(3).Set(reflect.ValueOf(data))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
61
utils/check/check.go
Normal file
61
utils/check/check.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var category = map[string]bool{
|
||||
"personalization": true,
|
||||
}
|
||||
|
||||
// CheckCategory 检查是否存在该类型
|
||||
func CheckCategory(key string) bool {
|
||||
_, ok := category[key]
|
||||
return ok
|
||||
}
|
||||
|
||||
// CheckValidS3Key 检查s3的文件名是否符合要求
|
||||
func CheckValidS3Key(key string) (bool, error) {
|
||||
if utf8.RuneCountInString(key) > 1024 {
|
||||
return false, errors.New("对象键长度超过 1024 字节")
|
||||
}
|
||||
|
||||
if strings.HasPrefix(key, "/") || strings.HasPrefix(key, ".") {
|
||||
return false, errors.New("对象键不应以 / 或 . 开头")
|
||||
}
|
||||
|
||||
if !utf8.ValidString(key) {
|
||||
return false, errors.New("对象键必须是 UTF-8 字符串")
|
||||
}
|
||||
|
||||
if hasControlCharacters(key) {
|
||||
return false, errors.New("对象键包含控制字符")
|
||||
}
|
||||
|
||||
if hasInvalidPatterns(key) {
|
||||
return false, errors.New("对象键包含无效的字符或模式")
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func hasControlCharacters(key string) bool {
|
||||
controlCharPattern := "[\\x00-\\x1F\\x7F]"
|
||||
match, _ := regexp.MatchString(controlCharPattern, key)
|
||||
return match
|
||||
}
|
||||
|
||||
func hasInvalidPatterns(key string) bool {
|
||||
invalidPatterns := []string{"[\\s]+$", "^\\s+", "\\\\", "//", "\\.\\."}
|
||||
for _, pattern := range invalidPatterns {
|
||||
match, _ := regexp.MatchString(pattern, key)
|
||||
if match {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
53
utils/format/s3keyname.go
Normal file
53
utils/format/s3keyname.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package format
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TypeFormatS3KeyName int
|
||||
|
||||
const (
|
||||
TypeS3KeyUser TypeFormatS3KeyName = 1 // 登录用户
|
||||
TypeS3KeyGuest TypeFormatS3KeyName = 2 // 游客
|
||||
)
|
||||
|
||||
// FormatS3KeyName 需要输入选
|
||||
func FormatS3KeyName(keytype TypeFormatS3KeyName, uid int64, now time.Time, env, category, name string) string {
|
||||
if keytype == TypeS3KeyUser {
|
||||
return FormatS3KeyNameUser(uid, now, env, category, name)
|
||||
} else if keytype == TypeS3KeyGuest {
|
||||
return FormatS3KeyNameGuest(uid, now, env, category, name)
|
||||
} else {
|
||||
panic("key type error")
|
||||
}
|
||||
}
|
||||
|
||||
// FormatS3KeyNameUser
|
||||
func FormatS3KeyNameUser(userid int64, now time.Time, env, category, name string) string {
|
||||
year, month, _ := now.Date()
|
||||
names := strings.Split(name, ".")
|
||||
var ext string
|
||||
if len(names) == 1 {
|
||||
name = names[0]
|
||||
} else if len(names) == 2 {
|
||||
name = names[0]
|
||||
ext = names[1]
|
||||
}
|
||||
return fmt.Sprintf("/%s/%s/%d/%04d%02d/%s_%d.%s", env, category, userid, year, int(month), name, now.Unix(), ext)
|
||||
}
|
||||
|
||||
// FormatS3KeyNameGuest 游客的格式化存储
|
||||
func FormatS3KeyNameGuest(guestid int64, now time.Time, env, category, name string) string {
|
||||
year, month, _ := now.Date()
|
||||
names := strings.Split(name, ".")
|
||||
var ext string
|
||||
if len(names) == 1 {
|
||||
name = names[0]
|
||||
} else if len(names) == 2 {
|
||||
name = names[0]
|
||||
ext = names[1]
|
||||
}
|
||||
return fmt.Sprintf("/%s/guest/%s/%d/%04d%02d/%s_%d.%s", env, category, guestid, year, int(month), name, now.Unix(), ext)
|
||||
}
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
// 字符串切片转int切片
|
||||
func StrSlicToIntSlice(input []string) ([]int, error) {
|
||||
newSlic := make([]int, 0, len(input))
|
||||
for _, p := range input {
|
||||
if p == "" {
|
||||
for _, element := range input {
|
||||
if element == "" {
|
||||
continue
|
||||
}
|
||||
val, err := strconv.Atoi(p)
|
||||
val, err := strconv.Atoi(element)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -23,11 +23,11 @@ func StrSlicToIntSlice(input []string) ([]int, error) {
|
||||
// 字符串切片转int64切片
|
||||
func StrSlicToInt64Slice(input []string) ([]int64, error) {
|
||||
newSlic := make([]int64, 0, len(input))
|
||||
for _, p := range input {
|
||||
if p == "" {
|
||||
for _, element := range input {
|
||||
if element == "" {
|
||||
continue
|
||||
}
|
||||
val, err := strconv.ParseInt(p, 10, 64)
|
||||
val, err := strconv.ParseInt(element, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
154
utils/fstests/basic.go
Normal file
154
utils/fstests/basic.go
Normal file
@@ -0,0 +1,154 @@
|
||||
package fstests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/474420502/requests"
|
||||
)
|
||||
|
||||
func GetEtcYamlPathAuto() string {
|
||||
var currentFilePath string
|
||||
var ok bool
|
||||
for i := 1; i < 4; i++ {
|
||||
_, currentFilePath, _, ok = runtime.Caller(i)
|
||||
if !ok {
|
||||
panic("Error: Unable to get the current file path.")
|
||||
|
||||
}
|
||||
dirs := strings.Split(currentFilePath, "/")
|
||||
if dirs[len(dirs)-2] != "fstests" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
curdir, err := filepath.Abs(currentFilePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
}
|
||||
|
||||
curdir = filepath.Dir(curdir)
|
||||
var limitCount = 10
|
||||
finfo, err := os.Stat(curdir + "/etc")
|
||||
for err != nil || !finfo.IsDir() {
|
||||
curdir = filepath.Dir(curdir)
|
||||
finfo, err = os.Stat(curdir + "/etc")
|
||||
limitCount--
|
||||
if limitCount <= 0 {
|
||||
panic("out limit")
|
||||
}
|
||||
}
|
||||
lidx := strings.LastIndex(curdir, "/")
|
||||
|
||||
return fmt.Sprintf("%s/etc/%s.yaml", curdir, curdir[lidx+1:])
|
||||
|
||||
}
|
||||
|
||||
func GetCurrentServiceName() string {
|
||||
_, currentFilePath, _, ok := runtime.Caller(1)
|
||||
if !ok {
|
||||
panic("Error: Unable to get the current file path.")
|
||||
|
||||
}
|
||||
|
||||
curdir, err := filepath.Abs(currentFilePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
}
|
||||
|
||||
curdir = filepath.Dir(curdir)
|
||||
var limitCount = 10
|
||||
finfo, err := os.Stat(curdir + "/etc")
|
||||
for err != nil || !finfo.IsDir() {
|
||||
curdir = filepath.Dir(curdir)
|
||||
finfo, err = os.Stat(curdir + "/etc")
|
||||
limitCount--
|
||||
if limitCount <= 0 {
|
||||
panic("out limit")
|
||||
}
|
||||
}
|
||||
lidx := strings.LastIndex(curdir, "/")
|
||||
// log.Println(curdir[lidx+1:])
|
||||
return curdir[lidx+1:]
|
||||
}
|
||||
|
||||
func GetSesssion() *requests.Session {
|
||||
ses := requests.NewSession()
|
||||
return ses
|
||||
}
|
||||
|
||||
func GetSessionWithUserToken(t *testing.T, server requests.ITestServer, Host string, Port int) *requests.Session {
|
||||
ses := requests.NewSession()
|
||||
tp := ses.Post(fmt.Sprintf("http://%s:%d/user/login", Host, Port))
|
||||
tp.SetBodyJson(map[string]interface{}{
|
||||
"name": "9107058@qq.com",
|
||||
"pwd": "$2y$13$2y4O4OIz/zcK5C0vlSc9LuSpjWySjInLBSe49yDkE.iURb.R1hDsy",
|
||||
})
|
||||
resp, err := tp.TestExecute(server)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
result := resp.Json()
|
||||
code := result.Get("code").Int()
|
||||
if code != 200 {
|
||||
t.Error("code is not 200")
|
||||
}
|
||||
|
||||
token := result.Get("data.token")
|
||||
if !token.Exists() {
|
||||
t.Error("data.token is not exists")
|
||||
}
|
||||
ses.Header.Add("Authorization", token.String())
|
||||
|
||||
return ses
|
||||
}
|
||||
|
||||
func GetBackendSessionWithUserToken(t *testing.T, server requests.ITestServer, Host string, Port int) *requests.Session {
|
||||
ses := requests.NewSession()
|
||||
tp := ses.Post(fmt.Sprintf("http://%s:%d/backend-user/login", Host, Port))
|
||||
tp.SetBodyJson(map[string]interface{}{
|
||||
"name": "admin@admin.com",
|
||||
"pwd": "ZnVzZW5fYmFja2VuZF8yMDIz47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU=",
|
||||
})
|
||||
resp, err := tp.TestExecute(server)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
result := resp.Json()
|
||||
code := result.Get("code").Int()
|
||||
if code != 200 {
|
||||
t.Error("code is not 200")
|
||||
}
|
||||
|
||||
token := result.Get("data.token")
|
||||
if !token.Exists() {
|
||||
t.Error("data.token is not exists")
|
||||
}
|
||||
ses.Header.Add("Authorization", token.String())
|
||||
|
||||
return ses
|
||||
}
|
||||
|
||||
func GetSesssionWithGuestToken(t *testing.T, server requests.ITestServer, Host string, Port int) *requests.Session {
|
||||
ses := requests.NewSession()
|
||||
tp := ses.Post(fmt.Sprintf("http://%s:%d/accept/cookie", Host, Port))
|
||||
|
||||
resp, err := tp.TestExecute(server)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
result := resp.Json()
|
||||
token := result.Get("data.token")
|
||||
if !token.Exists() {
|
||||
t.Error("data.token is not exists")
|
||||
}
|
||||
ses.Header.Add("Authorization", token.String())
|
||||
|
||||
return ses
|
||||
}
|
||||
@@ -6,7 +6,11 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// html转 Pdf dataType = 1 为网页url dataType = 2为网页内容 outFile为空则不保存(使用该方法需要安装工具 sudo apt-get install wkhtmltopdf)
|
||||
/*
|
||||
html转 Pdf
|
||||
dataType = 1 为网页url dataType = 2为网页内容
|
||||
outFile为空则不保存(使用该方法需要安装工具 sudo apt-get install wkhtmltopdf)
|
||||
*/
|
||||
func HtmlToPdfBase64(content string, dataType int, outFile ...string) (string, error) {
|
||||
pdfg, err := wkhtmltopdf.NewPDFGenerator()
|
||||
if err != nil {
|
||||
|
||||
1
utils/request_parser/parser.go
Normal file
1
utils/request_parser/parser.go
Normal file
@@ -0,0 +1 @@
|
||||
package requestparser
|
||||
Reference in New Issue
Block a user