diff --git a/common/contrib/files/pngcm/go.mod b/common/contrib/files/pngcm/go.mod new file mode 100644 index 000000000..7be2e167d --- /dev/null +++ b/common/contrib/files/pngcm/go.mod @@ -0,0 +1,34 @@ +module blazing/contrib/files/pngcm + +go 1.18 + +require github.com/gogf/gf/v2 v2.6.3 + +require ( + github.com/BurntSushi/toml v1.4.0 // indirect + github.com/clbanning/mxj/v2 v2.7.0 // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/grokify/html-strip-tags-go v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/stretchr/testify v1.11.1 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/common/contrib/files/pngcm/go.sum b/common/contrib/files/pngcm/go.sum new file mode 100644 index 000000000..eaae313a5 --- /dev/null +++ b/common/contrib/files/pngcm/go.sum @@ -0,0 +1,59 @@ +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= +github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gogf/gf/v2 v2.6.3 h1:DoqeuwU98wotpFoDSQEx8RZbmJdK8KdGiJtzJeqpyIo= +github.com/gogf/gf/v2 v2.6.3/go.mod h1:x2XONYcI4hRQ/4gMNbWHmZrNzSEIg20s2NULbzom5k0= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= +github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/common/contrib/files/pngcm/local.go b/common/contrib/files/pngcm/local.go new file mode 100644 index 000000000..3934e9cee --- /dev/null +++ b/common/contrib/files/pngcm/local.go @@ -0,0 +1,170 @@ +package pngcm + +import ( + "bytes" + "crypto/rand" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "mime/multipart" + "net/http" + "os" + "time" + + "blazing/cool" + "blazing/cool/coolfile" + + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/frame/g" +) + +// Pngcm 实现coolfile.Driver接口,用于远程图片上传 +type Pngcm struct{} + +// 远程上传接口响应结构 +type uploadResponse struct { + Code int `json:"code"` + Url string `json:"url"` + Message string `json:"message"` +} + +// Upload 上传文件到远程服务 +func (p *Pngcm) Upload(ctx g.Ctx, filepath, filename string) (string, error) { + // 检查本地文件是否存在 + if _, err := os.Stat(filepath); err != nil { + return "", gerror.Newf("上传文件不存在: %s, 错误: %v", filepath, err) + } + + // 生成27位随机字符串,类似PHP的Str::random(27) + randomStr, err := randString(27) + if err != nil { + return "", gerror.Newf("生成随机字符串失败: %v", err) + } + uuid := "o_" + randomStr + + // 构建表单数据 + var requestBody bytes.Buffer + writer := multipart.NewWriter(&requestBody) + + // 添加普通表单字段 + if err := writer.WriteField("name", filename); err != nil { + return "", gerror.Newf("写入name字段失败: %v", err) + } + if err := writer.WriteField("uuid", uuid); err != nil { + return "", gerror.Newf("写入uuid字段失败: %v", err) + } + if err := writer.WriteField("sign", fmt.Sprintf("%d", time.Now().Unix())); err != nil { + return "", gerror.Newf("写入sign字段失败: %v", err) + } + + // 添加文件字段 + file, err := os.Open(filepath) + if err != nil { + return "", gerror.Newf("打开文件失败: %v", err) + } + defer file.Close() + + fileField, err := writer.CreateFormFile("file", filename) + if err != nil { + return "", gerror.Newf("创建文件表单字段失败: %v", err) + } + if _, err := io.Copy(fileField, file); err != nil { + return "", gerror.Newf("复制文件内容失败: %v", err) + } + + // 完成表单构建 + if err := writer.Close(); err != nil { + return "", gerror.Newf("关闭表单写入器失败: %v", err) + } + + // 创建HTTP请求 + req, err := http.NewRequestWithContext(ctx, "POST", "https://img.wnflb2023.com/application/upload.php", &requestBody) + if err != nil { + return "", gerror.Newf("创建请求失败: %v", err) + } + + // 设置请求头 + req.Header.Set("Content-Type", writer.FormDataContentType()) + req.Header.Set("Referer", "https://img.wnflb2023.com/") + + // 发送请求 + client := &http.Client{ + Timeout: 30 * time.Second, // 设置超时时间 + } + resp, err := client.Do(req) + if err != nil { + return "", gerror.Newf("发送请求失败: %v", err) + } + defer resp.Body.Close() + + // 读取响应内容 + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return "", gerror.Newf("读取响应内容失败: %v", err) + } + + // 检查HTTP状态码 + if resp.StatusCode != http.StatusOK { + return "", gerror.Newf("接口返回非200状态码: %d, 响应内容: %s", resp.StatusCode, string(respBody)) + } + + // 解析JSON响应 + var uploadResp uploadResponse + if err := json.Unmarshal(respBody, &uploadResp); err != nil { + return "", gerror.Newf("解析响应JSON失败: %v, 响应内容: %s", err, string(respBody)) + } + + // 处理业务响应 + if uploadResp.Code == 200 { + return uploadResp.Url, nil + } else if uploadResp.Message != "" { + return "", gerror.Newf("上传失败请重试: %s", uploadResp.Message) + } else { + return "", gerror.Newf("上传失败!接口错误,响应内容: %s", string(respBody)) + } +} + +// GetMode 获取驱动模式信息 +func (p *Pngcm) GetMode() (data interface{}, err error) { + data = g.MapStrStr{ + "mode": cool.Config.File.Mode, + "type": "pngcm", + } + return +} + +// New 创建驱动实例 +func (p *Pngcm) New() coolfile.Driver { + return &Pngcm{} +} + +// New 实例化驱动 +func New() coolfile.Driver { + return &Pngcm{} +} + +// 生成指定长度的随机字符串(字母数字混合) +func randString(length int) (string, error) { + b := make([]byte, length) + _, err := rand.Read(b) + if err != nil { + return "", err + } + // 使用base64编码确保字符安全,然后截取指定长度 + return base64.URLEncoding.EncodeToString(b)[:length], nil +} + +func init() { + var ( + err error + driverObj = New() + driverNames = g.SliceStr{"pngcm"} + ) + // 注册驱动 + for _, driverName := range driverNames { + if err = coolfile.Register(driverName, driverObj); err != nil { + panic(err) + } + } +} diff --git a/modules/base/service/base_sys_log.go b/modules/base/service/base_sys_log.go index bab78c4e7..ab29cbc11 100644 --- a/modules/base/service/base_sys_log.go +++ b/modules/base/service/base_sys_log.go @@ -47,7 +47,7 @@ func (s *BaseSysLogService) Record(ctx g.Ctx) { baseSysLog.Action = r.Method + ":" + r.URL.Path baseSysLog.IP = r.GetClientIp() // 从内存或缓存查询IP - location, err := qqwry.QueryIP("119.29.29.29") + location, err := qqwry.QueryIP(baseSysLog.IP) if err != nil { fmt.Printf("错误:%v\n", err) return