国展报名

wp
workabee 8 months ago
parent 0772e8d0da
commit e45f0591ab

@ -0,0 +1,56 @@
package main
import (
"fmt"
appConfig "github.com/exhibition-main/internal/config"
"github.com/exhibition-main/pkg/router"
"github.com/exhibition-main/pkg/service"
"github.com/exhibition-main/pkg/tracing"
"github.com/exhibition-main/pkg/utils"
"github.com/go-redis/redis"
"github.com/robfig/cron/v3"
"github.com/streadway/amqp"
"go.uber.org/zap"
)
type App struct {
lg *zap.Logger
RedisClient *redis.Client
JaegerTracer *tracing.JaegerProvider
RabbitMqLink *amqp.Connection
}
func NewApp(lg *zap.Logger, RedisClient *redis.Client, JaegerTracer *tracing.JaegerProvider) *App {
return &App{
lg: lg,
RedisClient: RedisClient,
JaegerTracer: JaegerTracer,
}
}
func main() {
_, err := InitApp()
if err != nil {
panic(err)
}
modules()
r := router.NewRouter()
if appConfig.Data.System.IsHttps {
_ = r.RunTLS(fmt.Sprintf(":%d", appConfig.Data.System.Port), appConfig.Data.System.CertPath, appConfig.Data.System.KeyPath)
} else {
_ = r.Run(fmt.Sprintf(":%d", appConfig.Data.System.Port))
}
select {}
}
func modules() {
if err := utils.InitTrans("zh"); err != nil {
panic(err)
}
if appConfig.Data.System.Cron {
c := cron.New()
service.Task(c)
c.Start()
}
}

@ -0,0 +1,17 @@
// go:build wireinject
//go:build wireinject
// +build wireinject
package main
import (
"github.com/exhibition-main/pkg/cache"
"github.com/exhibition-main/pkg/logger"
"github.com/exhibition-main/pkg/tracing"
"github.com/google/wire"
)
func InitApp() (*App, error) {
wire.Build(logger.Provider, cache.RedisProvider, tracing.Provider, NewApp)
return &App{}, nil
}

@ -0,0 +1,23 @@
// Code generated by Wire. DO NOT EDIT.
//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject
package main
import (
"github.com/exhibition-main/pkg/cache"
"github.com/exhibition-main/pkg/logger"
"github.com/exhibition-main/pkg/tracing"
)
// Injectors from wire.go:
func InitApp() (*App, error) {
zapLogger := logger.ZapInit()
client := cache.NewRedis()
jaegerProvider := tracing.NewTracing()
app := NewApp(zapLogger, client, jaegerProvider)
return app, nil
}

@ -11,7 +11,10 @@ dubbo:
max-call-send-msg-size: 8000000
max-call-recv-msg-size: 8000000
references:
ExhibitionClientImpl:
protocol: tri
filter: tps
interface: com.fontree.microservices.common.Exhibition
logger:
zap-config:
level: error # 日志级别

@ -11,7 +11,10 @@ dubbo:
max-call-send-msg-size: 8000000
max-call-recv-msg-size: 8000000
references:
ExhibitionClientImpl:
protocol: tri
filter: tps
interface: com.fontree.microservices.common.Exhibition
logger:
zap-config:
level: error # 日志级别

@ -11,7 +11,10 @@ dubbo:
max-call-send-msg-size: 8000000
max-call-recv-msg-size: 8000000
references:
ExhibitionClientImpl:
protocol: tri
filter: tps
interface: com.fontree.microservices.common.Exhibition
logger:
zap-config:
level: error # 日志级别

@ -2,12 +2,25 @@ module github.com/exhibition-main
go 1.20
replace (
github.com/fonchain_enterprise/utils/aes => ../utils/aes
github.com/fonchain_enterprise/utils/chain => ../utils/chain
github.com/fonchain_enterprise/utils/feie => ../utils/feie
github.com/fonchain_enterprise/utils/ipAddrQuery => ../utils/ipAddrQuery
github.com/fonchain_enterprise/utils/jwt => ../utils/jwt
github.com/fonchain_enterprise/utils/logger => ../utils/logger
github.com/fonchain_enterprise/utils/objstorage => ../utils/objstorage
github.com/fonchain_enterprise/utils/rand => ../utils/rand
github.com/fonchain_enterprise/utils/utils => ../utils/utils
)
require (
dubbo.apache.org/dubbo-go/v3 v3.0.5
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/dubbogo/gost v1.13.2
github.com/dubbogo/grpc-go v1.42.10
github.com/dubbogo/triple v1.2.2-rc2
github.com/fonchain_enterprise/utils/objstorage v0.0.0-00010101000000-000000000000
github.com/gin-contrib/gzip v0.0.6
github.com/gin-contrib/pprof v1.4.0
github.com/gin-gonic/gin v1.9.0
@ -19,12 +32,17 @@ require (
github.com/google/wire v0.5.0
github.com/mwitkow/go-proto-validators v0.3.2
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/opentracing/opentracing-go v1.2.0
github.com/robfig/cron/v3 v3.0.1
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
github.com/satori/go.uuid v1.2.0
github.com/spf13/viper v1.7.0
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271
github.com/u2takey/ffmpeg-go v0.5.0
github.com/uber/jaeger-client-go v2.30.0+incompatible
go.uber.org/zap v1.21.0
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
google.golang.org/protobuf v1.28.1
)
@ -36,8 +54,12 @@ require (
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 // indirect
github.com/alibaba/sentinel-golang v1.0.4 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704 // indirect
github.com/aliyun/aliyun-oss-go-sdk v2.2.4+incompatible // indirect
github.com/apache/dubbo-getty v1.4.9-0.20221022181821-4dc6252ce98c // indirect
github.com/apache/dubbo-go-hessian2 v1.11.5 // indirect
github.com/aws/aws-sdk-go v1.38.20 // indirect
github.com/baidubce/bce-sdk-go v0.9.123 // indirect
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
@ -112,7 +134,7 @@ require (
github.com/prometheus/statsd_exporter v0.21.0 // indirect
github.com/shirou/gopsutil/v3 v3.22.2 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.1.2 // indirect
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/cast v1.3.0 // indirect
github.com/spf13/jwalterweatherman v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
@ -120,6 +142,7 @@ require (
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/u2takey/go-utils v0.3.1 // indirect
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
@ -138,6 +161,7 @@ require (
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
google.golang.org/appengine v1.6.6 // indirect
google.golang.org/genproto v0.0.0-20220504150022-98cd25cafc72 // indirect
google.golang.org/grpc v1.51.0 // indirect

@ -10,6 +10,79 @@ import (
var Data = new(AppConfig)
var (
AppMode string
HttpPort string
Key string
Cert string
IsHttps bool
RunHttps bool
Domain string
OssDomain string
ServerDM string
Env string
DriverUrl string
AppointUrl string
MaterialHost string
BosAk string
BosSk string
BosBucketName string
BosBaseDir string
BosUrl string
BosHttp string
BosDomain string
ProjectMapDir string
JaegerHost string
JaegerOpen bool
Cron bool
DingAccessToken string
DingUrl string
HolidayID string
HolidaySecret string
HolidaySingleUrl string
HolidayMultiUrl string
ErpAk string
ErpSk string
// rabbitmq
RabbitmqUser string
RabbitmqPassword string
RabbitmqHost string
RabbitmqPort int
RabbitmqVhost string
RabbitmqVhostArtwork string
RedisDB int
RedisAddr string
RedisPw string
//shop配置
ShopHost string
//ShopDetail string
// 地图
MapAppCode string
// es
ElasticHost string
SendIndexesUrl string
ChatGptHost string
ApiHost string
Level string
Filename string
MaxSize string
MaxAge string
MaxBackups string
YearGiftCheckHost string
Aliyun struct {
AccessKeyId string
AccessKeySecret string
}
)
type AppConfig struct {
System struct {
Domain string
@ -42,6 +115,15 @@ type AppConfig struct {
Key string
Expire int32
}
Bos struct {
AccessKeyId string
AccessKeySecret string
Endpoint string
Host string
BucketName string
BosBaseDir string
CdnHost string
}
}
func GetConf() (iniConf string, err error) {

@ -0,0 +1,12 @@
package model
type BaiduAccessToken struct {
Refresh_token string `json:"refresh_token"`
Expires_in uint64 `json:"expires_in"`
Scope string `json:"scope"`
Session_key string `json:"session_key"`
Access_token string `json:"access_token"`
Session_secret string `json:"session_secret"`
Error string `json:"error"`
Error_description string `json:"error_description"`
}

@ -6,10 +6,28 @@ const (
MODE_ENV = "MODE_ENV"
)
const (
HttpType = "http://"
HttpsType = "https://"
TmpArtworkDir = "./runtime/tmp/artworks"
TmpArtistDir = "./runtime/tmp/artists"
MediaPath = "./runtime/"
TplPath = "./data/"
ImgActionRotate = "rotate" //旋转
MediaTypeVideo = "video"
MediaTypeImage = "video"
)
type Response struct {
Status int `json:"status"`
Data interface{} `json:"data"`
Msg string `json:"msg"`
Code int `json:"code"`
Error error `json:"error"`
Err string `json:"err"`
Keys []string `json:"keys"`
Mark string `json:"mark,omitempty"`
Page *PageInfo `json:"page,omitempty"`
}
type PageInfo struct {

@ -24,5 +24,12 @@ const (
NEED_LOGIN = "请先登录"
INVALID_TOKEN = "token不合法"
INVALID_TOKEN = "token不合法"
INVALID_PARAMS = "参数错误"
JSON_UNMARSHAL = "Json解析错误"
ERROR_BAIDU_IMAGE = "图片审核不通过"
ERROR_BAIDU_FAIL = "图片审核失败"
ErrorUploadBos
)

@ -1,9 +1,12 @@
package response
import (
"fmt"
"github.com/exhibition-main/internal/model"
"github.com/exhibition-main/internal/msg"
"github.com/gin-gonic/gin"
"net/http"
"reflect"
)
func ResponseMsg(c *gin.Context, httpCode int, Resp model.Response) {
@ -25,3 +28,158 @@ func ResponseQuickMsg(c *gin.Context, Status uint8, Msg string, Data interface{}
Data: Data,
})
}
func Success(c *gin.Context, datas ...interface{}) {
var data any
if datas != nil {
data = datas[0]
}
dataFieldStr, _ := c.Get("dataField")
key := []string{"*"}
if dataFieldStr != "" && dataFieldStr != nil {
dataField := dataFieldStr.([]string)
key = dataField
if len(dataField) == 1 && dataField[0] == "*" { //不做处理
} else if len(dataField) >= 1 {
isList := isList(reflect.TypeOf(data).Elem())
// 是列表返回
if isList == false {
ChangeFromReflect(data, dataField)
} else {
ChangeRawFromReflect(data, dataField)
}
}
}
c.JSON(http.StatusOK, model.Response{
Status: msg.Ok,
Code: msg.StatusOK,
Data: data,
// Keys: dataField,
Keys: key,
})
c.Abort()
}
func IsContainString(items []string, item string) bool {
for _, eachItem := range items {
if eachItem == item {
return true
}
}
return false
}
func ChangeFromReflect(data interface{}, dataField []string) {
m := reflect.TypeOf(data).Elem()
for i := 0; i < m.NumField(); i++ {
fieldType := m.Field(i)
if IsContainString(dataField, fieldType.Name) == false {
field := reflect.ValueOf(data).Elem().FieldByName(fieldType.Name)
switch m.Field(i).Type.Name() {
case "int":
if field.CanSet() {
field.SetInt(0)
}
case "uint":
if field.CanSet() {
field.SetUint(0)
}
case "uint64":
if field.CanSet() {
field.SetUint(0)
}
case "string":
if field.CanSet() {
field.SetString("")
}
default:
if reflect.ValueOf(data).Elem().FieldByName(fieldType.Name).CanAddr() {
if reflect.ValueOf(data).Elem().FieldByName(fieldType.Name).Kind() == reflect.Slice {
field := reflect.ValueOf(data).Elem().FieldByName(fieldType.Name)
if field.CanSet() {
field.Set(reflect.MakeSlice(field.Type(), 0, 0))
}
}
if reflect.ValueOf(data).Elem().FieldByName(fieldType.Name).Kind() == reflect.Struct {
}
if reflect.ValueOf(data).Elem().FieldByName(fieldType.Name).Kind() == reflect.Ptr {
field := reflect.ValueOf(data).Elem().FieldByName(fieldType.Name)
if !reflect.ValueOf(data).Elem().FieldByName(fieldType.Name).IsNil() {
fieldType := reflect.ValueOf(data).Elem().FieldByName(fieldType.Name).Elem().Type()
if field.CanSet() {
field.Set(reflect.New(fieldType))
}
}
}
}
}
}
}
}
func ChangeRawFromReflect(data interface{}, dataField []string) {
sliceContent := reflect.ValueOf(data).Elem().FieldByName("Data")
for i := 0; i < sliceContent.Len(); i++ {
sliceContent.Index(i)
ChangeFromReflect(sliceContent.Index(i).Interface(), dataField)
}
}
func isList(m reflect.Type) bool {
dataExist := false
for i := 0; i < m.NumField(); i++ {
fieldType := m.Field(i)
if fieldType.Name == "Data" {
getValue := reflect.ValueOf(fieldType)
if getValue.Kind() != reflect.Slice {
dataExist = true
}
break
}
}
return dataExist
}
// Error 统一错误返回
func Error(c *gin.Context, code int, err error, message ...string) {
fmt.Println("err:", err)
status := msg.Fail
if code == msg.StatusUnauthorized {
status = msg.StatusUnauthorized
}
var msgStr string
if message != nil {
msgStr = message[0]
} else if err != nil {
msgStr = err.Error()
}
c.JSON(msg.StatusOK, model.Response{
Status: status,
Msg: msgStr,
Data: nil,
})
c.Abort()
}

@ -0,0 +1,58 @@
package logic
import (
"encoding/json"
"errors"
"fmt"
"github.com/dubbogo/gost/log/logger"
"github.com/exhibition-main/internal/model"
"github.com/exhibition-main/pkg/utils"
"time"
)
const (
grantType = "client_credentials"
clientId = "SjscdLEybzyxiV7lXKA5iSvZ"
clientSecret = "22fCduMdCarO6WWOi4WiSmt9rIeez3FW"
)
var accessToken string
var expiresIn uint64
func GetImageAccessToken() (string, error) {
var (
resObj model.BaiduAccessToken
err error
// daoAccessToken entity.AccessToken
)
if expiresIn == 0 || expiresIn < uint64(time.Now().Unix()) {
fmt.Println(1)
if resObj, err = getAccessTokenWithApi(); err != nil { //从链上获取
return "", err
}
accessToken = resObj.Access_token
expiresIn = resObj.Expires_in
}
return accessToken, nil
}
func getAccessTokenWithApi() (model.BaiduAccessToken, error) {
var (
resObj model.BaiduAccessToken
err error
)
url := "https://aip.baidubce.com/oauth/2.0/token"
urlReq := "?grant_type=" + grantType + "&client_id=" + clientId + "&client_secret=" + clientSecret
res := utils.Get(url + urlReq)
if err = json.Unmarshal([]byte(res), &resObj); err != nil {
logger.Error("getAccessTokenWithApi json err", err)
return resObj, err
}
if resObj.Error != "" {
logger.Error("getAccessTokenWithApi err", err)
return resObj, errors.New(resObj.Error_description)
}
return resObj, err
}

@ -0,0 +1,119 @@
package logic
import (
"github.com/dubbogo/gost/log/logger"
"github.com/rwcarlsen/goexif/exif"
"golang.org/x/image/bmp"
"image"
"image/jpeg"
"image/png"
"os"
"path"
"strings"
)
// ReadOrientation 方向判断
func ReadOrientation(filename string) (direct int, err error) {
file, err := os.Open(filename)
defer file.Close()
if err != nil {
logger.Error("failed to open file, err: ", err)
return
}
x, err := exif.Decode(file)
if err != nil {
logger.Error("failed to decode file, err: ", err)
return
}
orientation, err := x.Get(exif.Orientation)
if err != nil {
logger.Error("failed to orientation file, err: ", err)
return
}
direct, err = orientation.Int(0)
if err != nil {
logger.Error("failed to convert type file, err: ", err)
return
}
return
}
// 旋转90度
func rotate90(m image.Image) image.Image {
rotate90 := image.NewRGBA(image.Rect(0, 0, m.Bounds().Dy(), m.Bounds().Dx()))
// 矩阵旋转
for x := m.Bounds().Min.Y; x < m.Bounds().Max.Y; x++ {
for y := m.Bounds().Max.X - 1; y >= m.Bounds().Min.X; y-- {
// 设置像素点
rotate90.Set(m.Bounds().Max.Y-x, y, m.At(y, x))
}
}
return rotate90
}
// 旋转180度
func rotate180(m image.Image) image.Image {
rotate180 := image.NewRGBA(image.Rect(0, 0, m.Bounds().Dx(), m.Bounds().Dy()))
// 矩阵旋转
for x := m.Bounds().Min.X; x < m.Bounds().Max.X; x++ {
for y := m.Bounds().Min.Y; y < m.Bounds().Max.Y; y++ {
// 设置像素点
rotate180.Set(m.Bounds().Max.X-x, m.Bounds().Max.Y-y, m.At(x, y))
}
}
return rotate180
}
// 旋转270度
func rotate270(m image.Image) image.Image {
rotate270 := image.NewRGBA(image.Rect(0, 0, m.Bounds().Dy(), m.Bounds().Dx()))
// 矩阵旋转
for x := m.Bounds().Min.Y; x < m.Bounds().Max.Y; x++ {
for y := m.Bounds().Max.X - 1; y >= m.Bounds().Min.X; y-- {
// 设置像素点
rotate270.Set(x, m.Bounds().Max.X-y, m.At(y, x))
}
}
return rotate270
}
func MakeThumbnail(imagePath, savePath string) error {
prefix := strings.ToLower(path.Ext("./2.jpg"))
ori, err := ReadOrientation(imagePath)
if err != nil {
return err
}
file, _ := os.Open(imagePath)
defer file.Close()
img, _, err := image.Decode(file)
if err != nil {
return err
}
//苹果手机拍照的图片会有方向属性Orientation
//经过Decode和Encode编码处理后方向属性会丢失导致图片被旋转
switch ori {
case 6: //90度图片旋转
img = rotate90(img)
case 3:
img = rotate180(img)
case 8:
img = rotate270(img)
}
newImg, _ := os.Create(savePath)
defer newImg.Close()
switch prefix {
case ".jpg", ".jpeg":
err = jpeg.Encode(newImg, img, &jpeg.Options{Quality: 100})
case "png":
err = png.Encode(newImg, img)
case "bmp":
err = bmp.Encode(newImg, img)
default:
err = jpeg.Encode(newImg, img, &jpeg.Options{Quality: 100})
}
if err != nil {
logger.Error("Encode err", err)
return err
}
return nil
}

@ -2,6 +2,8 @@ package router
import (
"github.com/exhibition-main/internal/middleware"
"github.com/exhibition-main/pkg/service"
"github.com/exhibition-main/pkg/service/common"
"net/http"
"github.com/gin-contrib/gzip"
@ -16,49 +18,20 @@ func NewRouter() *gin.Engine {
r.Use(gzip.Gzip(gzip.DefaultCompression))
//加入日志中间件,跨域中间件
r.Use(middleware.NewLogger(), middleware.Cors(), middleware.GinRecovery(true))
//noAuth := r.Group("")
auth := r.Group("")
auth.Use(middleware.JWTAuthMiddleware())
//userAuth := auth.Group("user")
//{
// userAuth.POST("info", api.UserInfo)
// userAuth.POST("tickets", api.Tickets)
// userAuth.POST("login-out", api.LoginOut)
// userAuth.POST("destroy", api.Destroy)
//}
//userNoAuth := noAuth.Group("user")
//{
// userNoAuth.POST("login", api.Login)
//}
//goodsAuth := auth.Group("goods")
//{
// goodsAuth.POST("drink-list", api.DrinkList)
// goodsAuth.POST("ticket-list", api.TickerList)
// goodsAuth.POST("set-meal-list", api.SetMealList)
//}
//
//orderAuth := auth.Group("order")
//{
// orderAuth.POST("buy-goods", api.BuyGoods)
// orderAuth.POST("buy-tickets", api.BuyTicket)
// orderAuth.POST("buy-balance", api.BuyBalance)
// orderAuth.POST("buy-set-meal", api.BuySetMeal)
// orderAuth.POST("history-goods", api.HistoryGoods)
// orderAuth.POST("history-tickets", api.HistoryTickets)
// orderAuth.POST("history-balance", api.HistoryBalance)
//}
//
//orderNoAuth := noAuth.Group("order")
//{
// orderNoAuth.POST("wx_callback", api.WxCallback)
// orderAuth.POST("order-data-h5", api.OrderDataH5)
// orderAuth.POST("update-h5-order", api.UpdateH5Order)
//}
//
//miniNoAuth := noAuth.Group("mini")
//{
// miniNoAuth.POST("url-scheme", api.UrlScheme)
//}
// 上传
upload := auth.Group("upload")
{
upload.POST("img", common.UploadImg)
}
registerAuth := auth.Group("register")
{
registerAuth.POST("register_record_list", service.RegisterRecordList)
registerAuth.POST("check_by_phone", service.CheckPhone)
registerAuth.POST("save_register_info", service.SaveRegisterRecord)
}
//静态文件
r.StaticFS("/static", http.Dir("./runtime"))

@ -0,0 +1,309 @@
package common
import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"github.com/disintegration/imaging"
"github.com/dubbogo/gost/log/logger"
"github.com/exhibition-main/internal/config"
"github.com/exhibition-main/internal/model"
"github.com/exhibition-main/internal/msg"
"github.com/exhibition-main/internal/response"
"github.com/exhibition-main/pkg/logic"
"github.com/exhibition-main/pkg/utils"
"github.com/fonchain_enterprise/utils/objstorage"
"github.com/gin-gonic/gin"
uuid "github.com/satori/go.uuid"
ffmpeg "github.com/u2takey/ffmpeg-go"
"go.uber.org/zap"
"io/ioutil"
"mime/multipart"
"net/url"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"sync"
)
var (
wg sync.WaitGroup
)
const (
MediaPath = "./runtime/"
RouteType = "static/"
VideoType = "video"
ImageType = "image"
PngType = "png"
ArtworkFilePath = "artwork"
ArtworkChunkBasePath = "./runtime/tmp/artworks"
)
func UploadImg(c *gin.Context) {
var err error
source := c.PostForm("source")
mask := c.PostForm("mask")
action := c.PostForm("action")
if mask == "" {
mask = "default"
}
mediaType := c.PostForm("type")
logger.Errorf("UploadImg 1 %+v", mask)
var BasePath string
if mediaType == "" || mediaType == ImageType {
mediaType = ImageType
}
BasePath = fmt.Sprintf("%s%s", MediaPath, mediaType)
//BaseRoute = fmt.Sprintf("%s%s", RouteType, mediaType)
var isCompress int
if cStr, ok := c.GetPostForm("is_compress"); ok {
var errS error
isCompress, errS = strconv.Atoi(cStr)
if errS != nil {
response.ResponseQuickMsg(c, msg.Fail, errS.Error(), nil)
return
}
}
logger.Errorf("UploadImg 2 %+v", mask)
// 检验参数
if mask == "" || source == "" {
response.ResponseQuickMsg(c, msg.Fail, msg.INVALID_PARAMS, nil)
return
}
file, err := c.FormFile("file")
// 检验文件
if err != nil {
logger.Errorf("Upload FormFile err", err)
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
return
}
logger.Errorf("UploadImg 3 %+v", mask)
// 判断是不是视频或者需要压缩
var oriUrl string
if isCompress != 1 && mediaType != "video" && action == "" {
oriUrl, err = quickBos(file, mediaType, mask, source)
if err != nil {
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
return
}
response.ResponseQuickMsg(c, msg.Ok, msg.SUCCESS, map[string]interface{}{
"ori_url": oriUrl,
})
return
}
logger.Errorf("UploadImg 4 %+v", mask)
//创建文件名
fileExt := strings.ToLower(path.Ext(file.Filename))
filename := uuid.NewV4()
if err != nil {
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
return
}
fileFullName := fmt.Sprintf("%s%s", filename, fileExt)
//检测文件夹 不存在就创建
imgPath := fmt.Sprintf("%s/%s/%s", BasePath, source, mask)
_, err = utils.CheckDirPath(imgPath, true)
if err != nil {
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
return
}
dst := fmt.Sprintf("%s/%s", imgPath, fileFullName)
logger.Errorf("UploadImg 5 %+v", mask)
// 保存文件至指定路径
err = c.SaveUploadedFile(file, dst)
if err != nil {
logger.Errorf("Upload FormFile err", err)
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
return
}
logger.Errorf("UploadImg 6 %+v", mask)
if action == model.ImgActionRotate {
fileFullName = fmt.Sprintf("%s%s", filename, fileExt)
newDst := fmt.Sprintf("%s/%s_rotate%v", imgPath, filename, fileExt)
if err = logic.MakeThumbnail(dst, newDst); err != nil {
//ResponseQuickMsg(c, e.Failed, e.GetMsg(e.ERROR_ROTATE_IMG), nil)
//return
} else {
_ = os.Remove(dst)
dst = newDst
}
}
//localUrl := fmt.Sprintf("%s/%s/%s/%s/%s", config.ServerDM, BaseRoute, source, mask, fileFullName)
var data map[string]string = make(map[string]string, 2)
//data["ori_url"] = localUrl
if int32(isCompress) == 1 {
//压缩图片并存储在原图路径命名格式xx.jpg_small.jpg
fileFullName = fmt.Sprintf("%s_small%s", filename, fileExt)
newDst := fmt.Sprintf("%s/%s", imgPath, fileFullName)
//compressUrl := fmt.Sprintf("%s/%s/%s/%s/%s", config.ServerDM, BaseRoute, source, mask, fileFullName)
err = utils.CompressJPG(dst, newDst)
compressUrl, err := PutBos(newDst, mediaType, true)
if err != nil {
logger.Errorf("Upload compress err", err)
response.ResponseQuickMsg(c, msg.Fail, err.Error(), data)
return
}
data["compress_url"] = compressUrl
}
logger.Errorf("UploadImg 7 %+v", mask)
// 如果是视频需要截图图片做封面
if mediaType == VideoType {
videoCover := fmt.Sprintf("%s/%s", imgPath, filename)
_, err = GetSnapshot(dst, videoCover, 1)
if err != nil {
logger.Errorf("GetSnapshot err %+v", err.Error())
response.ResponseQuickMsg(c, msg.Fail, "获取封面失败", err.Error())
return
}
logger.Errorf("UploadImg 8 %+v", mask)
logger.Errorf("UploadImg 8.1 videoCover %+v", videoCover)
//data["cover_url"] = fmt.Sprintf("%s/%s/%s/%s/%s", config.ServerDM, BaseRoute, source, mask, fmt.Sprintf("%s.%s", filename, PngType))
coverUrl, err := PutBos(videoCover+"."+PngType, mediaType, true)
data["cover_url"] = coverUrl
if err != nil {
logger.Errorf("Upload GetSnapshot err", zap.Error(err))
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
return
}
}
ossUrl, err := PutBos(dst, mediaType, true)
if err != nil {
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
return
}
data["ori_url"] = ossUrl
response.ResponseQuickMsg(c, msg.Ok, msg.SUCCESS, data)
return
}
func GetSnapshot(videoPath, snapshotPath string, frameNum int) (snapshotName string, err error) {
buf := bytes.NewBuffer(nil)
err = ffmpeg.Input(videoPath).
Filter("select", ffmpeg.Args{fmt.Sprintf("gte(n,%d)", frameNum)}).
Output("pipe:", ffmpeg.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg"}).
WithOutput(buf, os.Stdout).
Run()
if err != nil {
logger.Errorf("GetSnapshot Input err:", zap.Error(err))
return "", err
}
img, err := imaging.Decode(buf)
if err != nil {
logger.Errorf("GetSnapshot Decode err:", zap.Error(err))
return "", err
}
err = imaging.Save(img, snapshotPath+"."+PngType)
if err != nil {
logger.Errorf("GetSnapshot Save err:", zap.Error(err))
return "", err
}
names := strings.Split(snapshotPath, "\\")
snapshotName = names[len(names)-1] + "." + PngType
return
}
func PutBos(filePath string, mediaType string, needRemove bool) (url string, err error) {
BOSClient, err := objstorage.NewBOS(config.BosAk, config.BosSk, objstorage.BOS_BJ)
if err != nil {
logger.Errorf("PutBos NewBOS err ", err)
err = errors.New(msg.ErrorUploadBos)
return
}
f, err := os.Open(filePath)
if err != nil {
logger.Errorf("PutBos Open err %+v", err.Error())
return
}
fileBytes, _ := ioutil.ReadAll(f)
f.Close()
//删除本地文件
if needRemove {
os.Remove(filePath)
}
if mediaType == "image" {
if err = BaiduCheckImage(fileBytes); err != nil {
return
}
}
filePath = strings.Replace(filePath, "./runtime", "", 1)
var objectName string = fmt.Sprintf("%s/%s%s", config.BosBaseDir, config.Env, filePath)
_, err = BOSClient.PutObjectFromBytes(config.BosBucketName, objectName, fileBytes)
if err != nil {
logger.Errorf("PutBos PutObject err %+v", err.Error())
err = errors.New(msg.ErrorUploadBos)
return
}
//url = fmt.Sprintf("%s%s%s/%s", config.BosHttp, config.BosBucketName, config.BosUrl, objectName)
url = fmt.Sprintf("%s%s/%s", config.BosHttp, config.BosDomain, objectName)
return
}
func quickBos(file *multipart.FileHeader, mediaType string, mask string, source string) (url string, err error) {
newFile, _ := file.Open()
defer newFile.Close()
uuids := uuid.NewV4()
filePath := fmt.Sprintf("%s/%s/%s/%s%s", mediaType, mask, source, uuids, filepath.Ext(file.Filename))
fileBytes, _ := ioutil.ReadAll(newFile)
if mediaType == "image" {
if err = BaiduCheckImage(fileBytes); err != nil {
return
}
}
var objectName string = fmt.Sprintf("%s/%s/%s", config.BosBaseDir, config.Env, filePath)
BOSClient, _ := objstorage.NewBOS(config.BosAk, config.BosSk, objstorage.BOS_BJ)
_, err = BOSClient.PutObjectFromBytes(config.BosBucketName, objectName, fileBytes)
if err != nil {
logger.Errorf("quickBos err", err)
return
}
//url = fmt.Sprintf("%s%s%s/%s", config.BosHttp, config.BosBucketName, config.BosUrl, objectName)
url = fmt.Sprintf("%s%s/%s", config.BosHttp, config.BosDomain, objectName)
return
}
// BaiduCheckImage 图片鉴黄
func BaiduCheckImage(imageByte []byte) (err error) {
return
var (
accesstoken string
response string
)
sourcestring := base64.StdEncoding.EncodeToString(imageByte)
if accesstoken, err = logic.GetImageAccessToken(); err != nil {
return err
}
host := "https://aip.baidubce.com/rest/2.0/solution/v1/img_censor/v2/user_defined?access_token=[" + accesstoken + "]"
if response, err = utils.PostForm(host, url.Values{"image": {sourcestring}}); err != nil {
logger.Error("user_defined PostForm err", err)
return err
}
var res struct {
ErrorCode int64 `json:"error_code"`
ErrorMsg string `json:"error_msg"`
Conclusion string `json:"conclusion"`
Log_id uint64 `json:"log_id"`
IsHitMd5 bool `json:"isHitMd5"`
ConclusionType int64 `json:"conclusionType"`
}
if err = json.Unmarshal([]byte(response), &res); err != nil {
err = errors.New(msg.JSON_UNMARSHAL)
return
}
logger.Error("user_defined res", res)
if res.ErrorCode != 0 || res.ErrorMsg != "" {
return errors.New(msg.ERROR_BAIDU_FAIL)
}
if res.Conclusion != "合规" && res.Conclusion != "疑似" {
return errors.New(msg.ERROR_BAIDU_IMAGE)
}
return nil
}

@ -0,0 +1,14 @@
package service
import (
"dubbo.apache.org/dubbo-go/v3/config"
"github.com/robfig/cron/v3"
)
func Task(c *cron.Cron) {
if config.GetConsumerService("ArtworkClientImpl") != nil {
_, _ = c.AddFunc("@every 5m", func() {
})
}
}

@ -3,13 +3,14 @@ package service
import (
"dubbo.apache.org/dubbo-go/v3/config"
_ "dubbo.apache.org/dubbo-go/v3/imports"
"github.com/exhibition-main/api/exhibition"
appConfig "github.com/exhibition-main/internal/config"
)
//var GrpcAccountClientImpl = new(account.AccountClientImpl)
var GrpcExhibitionClientImpl = new(exhibition.ExhibitionClientImpl)
func init() {
//config.SetConsumerService(GrpcAccountClientImpl)
config.SetConsumerService(GrpcExhibitionClientImpl)
appConfig.GetOptions()
if err := config.Load(); err != nil {
panic(err)

@ -1 +1,61 @@
package service
import (
"context"
"github.com/dubbogo/gost/log/logger"
"github.com/exhibition-main/api/exhibition"
"github.com/exhibition-main/internal/msg"
"github.com/exhibition-main/internal/response"
"github.com/gin-gonic/gin"
)
func RegisterRecordList(c *gin.Context) {
var recordListReq exhibition.RecordListReq
if err := c.ShouldBind(&recordListReq); err != nil {
logger.Errorf("RegisterRecordList ShouldBind err", err)
response.ResponseQuickMsg(c, msg.Fail, msg.INVALID_PARAMS, nil)
return
}
resp, err := GrpcExhibitionClientImpl.RegisterRecordList(context.Background(), &recordListReq)
if err != nil {
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
return
}
response.ResponseQuickMsg(c, msg.Ok, resp.Msg, resp)
return
}
func CheckPhone(c *gin.Context) {
var registerInfo exhibition.RegisterInfo
if err := c.ShouldBind(&registerInfo); err != nil {
logger.Errorf("CheckPhone ShouldBind err", err)
response.ResponseQuickMsg(c, msg.Fail, msg.INVALID_PARAMS, nil)
return
}
resp, err := GrpcExhibitionClientImpl.CheckPhone(context.Background(), &registerInfo)
if err != nil {
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
return
}
response.ResponseQuickMsg(c, msg.Ok, resp.Msg, resp)
return
}
func SaveRegisterRecord(c *gin.Context) {
var registerInfo exhibition.RegisterInfo
if err := c.ShouldBind(&registerInfo); err != nil {
logger.Errorf("SaveRegisterRecord ShouldBind err", err)
response.ResponseQuickMsg(c, msg.Fail, msg.INVALID_PARAMS, nil)
return
}
resp, err := GrpcExhibitionClientImpl.SaveRegisterRecord(context.Background(), &registerInfo)
if err != nil {
response.ResponseQuickMsg(c, msg.Fail, err.Error(), nil)
return
}
response.ResponseQuickMsg(c, msg.Ok, resp.Msg, resp)
return
}

@ -0,0 +1,82 @@
package utils
import (
"bytes"
"errors"
"fmt"
"github.com/exhibition-main/internal/msg"
"github.com/nfnt/resize"
"go.uber.org/zap"
"image"
"image/jpeg"
"os"
)
const (
CompressLimit = 1024 * 1024 * 1
MaxHeight uint = 600
)
func CheckDirPath(path string, create bool) (exists bool, err error) {
exists = false
if path == "" {
err = errors.New(msg.INVALID_PARAMS)
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
}
// CompressJPG 压缩图片,并返回缩略图路径
func CompressJPG(dst string, newDst string) (err error) {
filebytes, err := os.ReadFile(dst)
if err != nil {
return err
}
compressbytes := compressImageResource(filebytes)
fo, err := os.Create(newDst)
defer fo.Close()
if err != nil {
return err
}
_, err = fo.Write(compressbytes)
if err != nil {
return err
}
return nil
}
func compressImageResource(data []byte) []byte {
if len(data) < CompressLimit {
return data
}
img, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
return data
}
m := resize.Resize(0, MaxHeight, img, resize.Lanczos3)
buf := bytes.Buffer{}
err = jpeg.Encode(&buf, m, &jpeg.Options{Quality: 100})
if err != nil {
zap.L().Error("compressImageResource Encode err", zap.Error(err))
return data
}
if buf.Len() > len(data) {
return data
}
fmt.Println(buf.Len())
if buf.Len() >= CompressLimit {
bytes := compressImageResource(buf.Bytes())
return bytes
}
return buf.Bytes()
}

@ -0,0 +1,47 @@
package utils
import (
"bytes"
"io"
"io/ioutil"
"net/http"
"net/url"
"time"
)
// 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 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()
}
Loading…
Cancel
Save