feat:合图功能,封装上传base64等等
This commit is contained in:
		
							parent
							
								
									2f1ef81263
								
							
						
					
					
						commit
						d810b87c09
					
				
							
								
								
									
										19
									
								
								server/resource/etc/resource.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								server/resource/etc/resource.yaml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | Name: resource | ||||||
|  | Host: 0.0.0.0 | ||||||
|  | Port: 9916 | ||||||
|  | Timeout: 15000 #服务超时时间(毫秒) | ||||||
|  | SourceMysql: fusentest:XErSYmLELKMnf3Dh@tcp(110.41.19.98:3306)/fusentest | ||||||
|  | Auth: | ||||||
|  |     AccessSecret: fusen2023 | ||||||
|  |     AccessExpire: 2592000 | ||||||
|  |     RefreshAfter: 1592000 | ||||||
|  | SourceRabbitMq: amqp://rabbit001:rabbit001129@110.41.19.98:5672 | ||||||
|  | AWS: | ||||||
|  |     S3: | ||||||
|  |         Credentials: | ||||||
|  |             AccessKeyID: AKIAZB2JKUXDPNRP4YT2 | ||||||
|  |             Secret: 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 | ||||||
|  |             Token: | ||||||
|  | BLMService: | ||||||
|  |     LogoCombine: | ||||||
|  |         Url: "http://192.168.1.7:45678/LogoCombine" | ||||||
							
								
								
									
										28
									
								
								server/resource/internal/config/config.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								server/resource/internal/config/config.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | package config | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fusenapi/server/resource/internal/types" | ||||||
|  | 
 | ||||||
|  | 	"github.com/zeromicro/go-zero/rest" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type Config struct { | ||||||
|  | 	rest.RestConf | ||||||
|  | 	SourceMysql    string | ||||||
|  | 	Auth           types.Auth | ||||||
|  | 	SourceRabbitMq string | ||||||
|  | 	AWS            struct { | ||||||
|  | 		S3 struct { | ||||||
|  | 			Credentials struct { | ||||||
|  | 				AccessKeyID string | ||||||
|  | 				Secret      string | ||||||
|  | 				Token       string | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	BLMService struct { | ||||||
|  | 		LogoCombine struct { | ||||||
|  | 			Url string | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								server/resource/internal/handler/logocombinehandler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								server/resource/internal/handler/logocombinehandler.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | |||||||
|  | package handler | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 	"reflect" | ||||||
|  | 
 | ||||||
|  | 	"fusenapi/utils/basic" | ||||||
|  | 
 | ||||||
|  | 	"fusenapi/server/resource/internal/logic" | ||||||
|  | 	"fusenapi/server/resource/internal/svc" | ||||||
|  | 	"fusenapi/server/resource/internal/types" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func LogoCombineHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { | ||||||
|  | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 
 | ||||||
|  | 		var req types.LogoCombineReq | ||||||
|  | 		userinfo, err := basic.RequestParse(w, r, svcCtx, &req) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// 创建一个业务逻辑层实例 | ||||||
|  | 		l := logic.NewLogoCombineLogic(r.Context(), svcCtx) | ||||||
|  | 
 | ||||||
|  | 		rl := reflect.ValueOf(l) | ||||||
|  | 		basic.BeforeLogic(w, r, rl) | ||||||
|  | 
 | ||||||
|  | 		resp := l.LogoCombine(&req, userinfo) | ||||||
|  | 
 | ||||||
|  | 		if !basic.AfterLogic(w, r, rl, resp) { | ||||||
|  | 			basic.NormalAfterLogic(w, r, resp) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								server/resource/internal/handler/routes.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								server/resource/internal/handler/routes.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | // Code generated by goctl. DO NOT EDIT. | ||||||
|  | package handler | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"fusenapi/server/resource/internal/svc" | ||||||
|  | 
 | ||||||
|  | 	"github.com/zeromicro/go-zero/rest" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { | ||||||
|  | 	server.AddRoutes( | ||||||
|  | 		[]rest.Route{ | ||||||
|  | 			{ | ||||||
|  | 				Method:  http.MethodPost, | ||||||
|  | 				Path:    "/api/resource/logo-combine", | ||||||
|  | 				Handler: LogoCombineHandler(serverCtx), | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	) | ||||||
|  | } | ||||||
							
								
								
									
										179
									
								
								server/resource/internal/logic/logocombinelogic.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								server/resource/internal/logic/logocombinelogic.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,179 @@ | |||||||
|  | package logic | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"fusenapi/model/gmodel" | ||||||
|  | 	"fusenapi/utils/auth" | ||||||
|  | 	"fusenapi/utils/basic" | ||||||
|  | 	"fusenapi/utils/file" | ||||||
|  | 	"fusenapi/utils/hash" | ||||||
|  | 	"io" | ||||||
|  | 	"net/http" | ||||||
|  | 	"strings" | ||||||
|  | 
 | ||||||
|  | 	"context" | ||||||
|  | 
 | ||||||
|  | 	"fusenapi/server/resource/internal/svc" | ||||||
|  | 	"fusenapi/server/resource/internal/types" | ||||||
|  | 
 | ||||||
|  | 	"github.com/zeromicro/go-zero/core/logx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type LogoCombineLogic struct { | ||||||
|  | 	logx.Logger | ||||||
|  | 	ctx    context.Context | ||||||
|  | 	svcCtx *svc.ServiceContext | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewLogoCombineLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LogoCombineLogic { | ||||||
|  | 	return &LogoCombineLogic{ | ||||||
|  | 		Logger: logx.WithContext(ctx), | ||||||
|  | 		ctx:    ctx, | ||||||
|  | 		svcCtx: svcCtx, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // 处理进入前逻辑w,r | ||||||
|  | // func (l *LogoCombineLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) { | ||||||
|  | // } | ||||||
|  | 
 | ||||||
|  | // 处理逻辑后 w,r 如:重定向, resp 必须重新处理 | ||||||
|  | // func (l *LogoCombineLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) { | ||||||
|  | // // httpx.OkJsonCtx(r.Context(), w, resp) | ||||||
|  | // } | ||||||
|  | 
 | ||||||
|  | func (l *LogoCombineLogic) LogoCombine(req *types.LogoCombineReq, userinfo *auth.UserInfo) (resp *basic.Response) { | ||||||
|  | 	// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) | ||||||
|  | 	// userinfo 传入值时, 一定不为null | ||||||
|  | 
 | ||||||
|  | 	if userinfo.IsOnlooker() { | ||||||
|  | 		// 如果是,返回未授权的错误码 | ||||||
|  | 		return resp.SetStatus(basic.CodeUnAuth) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var userId int64 | ||||||
|  | 	var guestId int64 | ||||||
|  | 
 | ||||||
|  | 	// 检查用户是否是游客 | ||||||
|  | 	if userinfo.IsGuest() { | ||||||
|  | 		// 如果是,使用游客ID和游客键名格式 | ||||||
|  | 		guestId = userinfo.GuestId | ||||||
|  | 	} else { | ||||||
|  | 		// 否则,使用用户ID和用户键名格式 | ||||||
|  | 		userId = userinfo.UserId | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// 根据hash 查询数据资源 | ||||||
|  | 	var resourceId string = hash.JsonHashKey(req.ResourceKey) | ||||||
|  | 	resourceModel := gmodel.NewFsResourceModel(l.svcCtx.MysqlConn) | ||||||
|  | 	resourceInfo, err := resourceModel.FindOneById(l.ctx, resourceId) | ||||||
|  | 	if err == nil && resourceInfo.ResourceId != "" { | ||||||
|  | 		return resp.SetStatus(basic.CodeOK, map[string]interface{}{ | ||||||
|  | 			"resource_id":       resourceId, | ||||||
|  | 			"resource_url":      resourceInfo.ResourceUrl, | ||||||
|  | 			"resource_metadata": resourceInfo.Metadata, | ||||||
|  | 		}) | ||||||
|  | 	} else { | ||||||
|  | 		if err != nil { | ||||||
|  | 			logx.Error(err) | ||||||
|  | 			return resp.SetStatus(basic.CodeDbSqlErr, "LogoCombine error") | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// 没有查到,先根据模版id 查询模版数据 请求算法数据 | ||||||
|  | 	productTemplateV2Model := gmodel.NewFsProductTemplateV2Model(l.svcCtx.MysqlConn) | ||||||
|  | 	productTemplateV2Info, err := productTemplateV2Model.FindOne(l.ctx, req.TemplateId) | ||||||
|  | 
 | ||||||
|  | 	if err != nil { | ||||||
|  | 		logx.Error(err) | ||||||
|  | 		return resp.SetStatus(basic.CodeDbSqlErr, "LogoCombine error") | ||||||
|  | 	} | ||||||
|  | 	var groupOptions map[string]interface{} | ||||||
|  | 	if productTemplateV2Info.GroupOptions != nil { | ||||||
|  | 		err = json.Unmarshal([]byte(*productTemplateV2Info.GroupOptions), &groupOptions) | ||||||
|  | 
 | ||||||
|  | 		if err != nil { | ||||||
|  | 			logx.Error(err) | ||||||
|  | 			return resp.SetStatus(basic.CodeDbSqlErr, "LogoCombine error Unmarshal groupOptions") | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var materialList []interface{} | ||||||
|  | 	if productTemplateV2Info.TemplateInfo != nil { | ||||||
|  | 		var templateInfo map[string]interface{} | ||||||
|  | 		err = json.Unmarshal([]byte(*productTemplateV2Info.TemplateInfo), &templateInfo) | ||||||
|  | 
 | ||||||
|  | 		if err != nil { | ||||||
|  | 			logx.Error(err) | ||||||
|  | 			return resp.SetStatus(basic.CodeDbSqlErr, "LogoCombine error Unmarshal templateInfo") | ||||||
|  | 		} | ||||||
|  | 		materialList = templateInfo["materialList"].([]interface{}) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var moduleDataMap = make(map[string]interface{}, 4) | ||||||
|  | 	moduleDataMap["id"] = productTemplateV2Info.Id | ||||||
|  | 	moduleDataMap["material"] = productTemplateV2Info.MaterialImg | ||||||
|  | 	moduleDataMap["groupOptions"] = groupOptions | ||||||
|  | 	moduleDataMap["materialList"] = materialList | ||||||
|  | 
 | ||||||
|  | 	var combineParam map[string]interface{} | ||||||
|  | 	json.Unmarshal([]byte(req.CombineParam), &combineParam) | ||||||
|  | 	var postMap = make(map[string]interface{}, 2) | ||||||
|  | 	postMap["module_data"] = moduleDataMap | ||||||
|  | 	postMap["param_data"] = combineParam | ||||||
|  | 	postMapB, _ := json.Marshal(postMap) | ||||||
|  | 
 | ||||||
|  | 	result, err := http.Post(l.svcCtx.Config.BLMService.LogoCombine.Url, "application/json", strings.NewReader(string(postMapB))) | ||||||
|  | 	if err != nil { | ||||||
|  | 		logx.Error(err) | ||||||
|  | 		return resp.SetStatus(basic.CodeFileLogoCombineErr, "service post fail") | ||||||
|  | 	} | ||||||
|  | 	defer result.Body.Close() | ||||||
|  | 	b, err := io.ReadAll(result.Body) | ||||||
|  | 	if err != nil { | ||||||
|  | 		logx.Error(err) | ||||||
|  | 		return resp.SetStatus(basic.CodeFileLogoCombineErr, "service read fail") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if string(b) == "Internal Server Error" { | ||||||
|  | 		return resp.SetStatus(basic.CodeFileLogoCombineErr, "service read fail") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var resultData map[string]interface{} | ||||||
|  | 	err = json.Unmarshal(b, &resultData) | ||||||
|  | 	if err != nil { | ||||||
|  | 		logx.Error(err) | ||||||
|  | 		return resp.SetStatus(basic.CodeFileLogoCombineErr, "service read fail") | ||||||
|  | 	} | ||||||
|  | 	// { | ||||||
|  | 	// 	id: "", | ||||||
|  | 	// 	logo_url:"https://s3.amazon.com/xxxx", | ||||||
|  | 	// 	result: "$saa541afaldjaldjasldjsadjsapsaasda" | ||||||
|  | 	// } | ||||||
|  | 	var fileBase = resultData["result"] | ||||||
|  | 
 | ||||||
|  | 	// 上传文件 | ||||||
|  | 	var upload = file.Upload{ | ||||||
|  | 		Ctx:        l.ctx, | ||||||
|  | 		MysqlConn:  l.svcCtx.MysqlConn, | ||||||
|  | 		AwsSession: l.svcCtx.AwsSession, | ||||||
|  | 	} | ||||||
|  | 	uploadRes, err := upload.UploadFileByBase64(&file.UploadBaseReq{ | ||||||
|  | 		FileHash:     resourceId, | ||||||
|  | 		FileData:     fileBase.(string), | ||||||
|  | 		UploadBucket: 1, | ||||||
|  | 		ApiType:      2, | ||||||
|  | 		UserId:       userId, | ||||||
|  | 		GuestId:      guestId, | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		logx.Error(err) | ||||||
|  | 		return resp.SetStatus(basic.CodeFileLogoCombineErr, "LogoCombine error upload file failed") | ||||||
|  | 	} | ||||||
|  | 	// 返回成功的响应和上传URL | ||||||
|  | 	return resp.SetStatus(basic.CodeOK, map[string]interface{}{ | ||||||
|  | 		"resource_id":       resourceId, | ||||||
|  | 		"resource_url":      uploadRes.ResourceUrl, | ||||||
|  | 		"resource_metadata": "", | ||||||
|  | 	}) | ||||||
|  | } | ||||||
							
								
								
									
										71
									
								
								server/resource/internal/svc/servicecontext.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								server/resource/internal/svc/servicecontext.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | |||||||
|  | package svc | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"fusenapi/server/resource/internal/config" | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"fusenapi/initalize" | ||||||
|  | 	"fusenapi/model/gmodel" | ||||||
|  | 
 | ||||||
|  | 	"github.com/aws/aws-sdk-go/aws" | ||||||
|  | 	"github.com/aws/aws-sdk-go/aws/credentials" | ||||||
|  | 	"github.com/aws/aws-sdk-go/aws/session" | ||||||
|  | 	"github.com/golang-jwt/jwt" | ||||||
|  | 	"gorm.io/gorm" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type ServiceContext struct { | ||||||
|  | 	Config config.Config | ||||||
|  | 
 | ||||||
|  | 	MysqlConn  *gorm.DB | ||||||
|  | 	AllModels  *gmodel.AllModelsGen | ||||||
|  | 	RabbitMq   *initalize.RabbitMqHandle | ||||||
|  | 	AwsSession *session.Session | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewServiceContext(c config.Config) *ServiceContext { | ||||||
|  | 	config := aws.Config{ | ||||||
|  | 		Credentials: credentials.NewStaticCredentials(c.AWS.S3.Credentials.AccessKeyID, c.AWS.S3.Credentials.Secret, c.AWS.S3.Credentials.Token), | ||||||
|  | 	} | ||||||
|  | 	initalize.InitRabbitMq(c.SourceRabbitMq, nil) | ||||||
|  | 	return &ServiceContext{ | ||||||
|  | 		Config:     c, | ||||||
|  | 		MysqlConn:  initalize.InitMysql(c.SourceMysql), | ||||||
|  | 		AllModels:  gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)), | ||||||
|  | 		RabbitMq:   initalize.InitRabbitMq(c.SourceRabbitMq, nil), | ||||||
|  | 		AwsSession: session.Must(session.NewSession(&config)), | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (svcCtx *ServiceContext) ParseJwtToken(r *http.Request) (jwt.MapClaims, error) { | ||||||
|  | 	AuthKey := r.Header.Get("Authorization") | ||||||
|  | 	if AuthKey == "" { | ||||||
|  | 		return nil, nil | ||||||
|  | 	} | ||||||
|  | 	AuthKey = AuthKey[7:] | ||||||
|  | 
 | ||||||
|  | 	if len(AuthKey) <= 50 { | ||||||
|  | 		return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey))) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	token, err := jwt.Parse(AuthKey, func(token *jwt.Token) (interface{}, error) { | ||||||
|  | 		// 检查签名方法是否为 HS256 | ||||||
|  | 		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { | ||||||
|  | 			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) | ||||||
|  | 		} | ||||||
|  | 		// 返回用于验证签名的密钥 | ||||||
|  | 		return []byte(svcCtx.Config.Auth.AccessSecret), nil | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, errors.New(fmt.Sprint("Error parsing token:", err)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// 验证成功返回 | ||||||
|  | 	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { | ||||||
|  | 		return claims, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil, errors.New(fmt.Sprint("Invalid token", err)) | ||||||
|  | } | ||||||
							
								
								
									
										81
									
								
								server/resource/internal/types/types.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								server/resource/internal/types/types.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,81 @@ | |||||||
|  | // Code generated by goctl. DO NOT EDIT. | ||||||
|  | package types | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fusenapi/utils/basic" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type LogoCombineReq struct { | ||||||
|  | 	ResourceKey  string `form:"resource_key"`  // 资源唯一标识 | ||||||
|  | 	CombineParam string `form:"combine_param"` // 合图参数 | ||||||
|  | 	TemplateId   int64  `form:"template_id"`   // 合图参数 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Request struct { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Response struct { | ||||||
|  | 	Code    int         `json:"code"` | ||||||
|  | 	Message string      `json:"msg"` | ||||||
|  | 	Data    interface{} `json:"data"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Auth struct { | ||||||
|  | 	AccessSecret string `json:"accessSecret"` | ||||||
|  | 	AccessExpire int64  `json:"accessExpire"` | ||||||
|  | 	RefreshAfter int64  `json:"refreshAfter"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type File struct { | ||||||
|  | 	Filename string              `fsfile:"filename"` | ||||||
|  | 	Header   map[string][]string `fsfile:"header"` | ||||||
|  | 	Size     int64               `fsfile:"size"` | ||||||
|  | 	Data     []byte              `fsfile:"data"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Meta struct { | ||||||
|  | 	TotalCount  int64 `json:"totalCount"` | ||||||
|  | 	PageCount   int64 `json:"pageCount"` | ||||||
|  | 	CurrentPage int   `json:"currentPage"` | ||||||
|  | 	PerPage     int   `json:"perPage"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Set 设置Response的Code和Message值 | ||||||
|  | func (resp *Response) Set(Code int, Message string) *Response { | ||||||
|  | 	return &Response{ | ||||||
|  | 		Code:    Code, | ||||||
|  | 		Message: Message, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Set 设置整个Response | ||||||
|  | func (resp *Response) SetWithData(Code int, Message string, Data interface{}) *Response { | ||||||
|  | 	return &Response{ | ||||||
|  | 		Code:    Code, | ||||||
|  | 		Message: Message, | ||||||
|  | 		Data:    Data, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetStatus 设置默认StatusResponse(内部自定义) 默认msg, 可以带data, data只使用一个参数 | ||||||
|  | func (resp *Response) SetStatus(sr *basic.StatusResponse, data ...interface{}) *Response { | ||||||
|  | 	newResp := &Response{ | ||||||
|  | 		Code: sr.Code, | ||||||
|  | 	} | ||||||
|  | 	if len(data) == 1 { | ||||||
|  | 		newResp.Data = data[0] | ||||||
|  | 	} | ||||||
|  | 	return newResp | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetStatusWithMessage 设置默认StatusResponse(内部自定义) 非默认msg, 可以带data, data只使用一个参数 | ||||||
|  | func (resp *Response) SetStatusWithMessage(sr *basic.StatusResponse, msg string, data ...interface{}) *Response { | ||||||
|  | 	newResp := &Response{ | ||||||
|  | 		Code:    sr.Code, | ||||||
|  | 		Message: msg, | ||||||
|  | 	} | ||||||
|  | 	if len(data) == 1 { | ||||||
|  | 		newResp.Data = data[0] | ||||||
|  | 	} | ||||||
|  | 	return newResp | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								server/resource/resource.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								server/resource/resource.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | |||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"flag" | ||||||
|  | 	"fmt" | ||||||
|  | 	"net/http" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"fusenapi/utils/auth" | ||||||
|  | 
 | ||||||
|  | 	"fusenapi/server/resource/internal/config" | ||||||
|  | 	"fusenapi/server/resource/internal/handler" | ||||||
|  | 	"fusenapi/server/resource/internal/svc" | ||||||
|  | 
 | ||||||
|  | 	"github.com/zeromicro/go-zero/core/conf" | ||||||
|  | 	"github.com/zeromicro/go-zero/rest" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var configFile = flag.String("f", "etc/resource.yaml", "the config file") | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	flag.Parse() | ||||||
|  | 
 | ||||||
|  | 	var c config.Config | ||||||
|  | 	conf.MustLoad(*configFile, &c) | ||||||
|  | 	c.Timeout = int64(time.Second * 15) | ||||||
|  | 	server := rest.MustNewServer(c.RestConf, rest.WithCustomCors(auth.FsCors, func(w http.ResponseWriter) { | ||||||
|  | 	})) | ||||||
|  | 	defer server.Stop() | ||||||
|  | 
 | ||||||
|  | 	ctx := svc.NewServiceContext(c) | ||||||
|  | 	handler.RegisterHandlers(server, ctx) | ||||||
|  | 
 | ||||||
|  | 	fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port) | ||||||
|  | 	server.Start() | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								server/resource/resource_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								server/resource/resource_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // var configFile = flag.String("f", "etc/home-user-auth.yaml", "the config file") | ||||||
|  | 
 | ||||||
|  | func TestMain(t *testing.T) { | ||||||
|  | 	// log.Println(model.RawFieldNames[FsCanteenType]()) | ||||||
|  | 	main() | ||||||
|  | } | ||||||
| @ -87,8 +87,7 @@ func (l *UploadLogoLogic) UploadLogo(req *types.UploadLogoReq, userinfo *auth.Us | |||||||
| 	postMap["logo_url"] = req.ResourceUrl | 	postMap["logo_url"] = req.ResourceUrl | ||||||
| 	postMapB, _ := json.Marshal(postMap) | 	postMapB, _ := json.Marshal(postMap) | ||||||
| 
 | 
 | ||||||
| 	contentType := "application/json" | 	result, err := http.Post(l.svcCtx.Config.BLMService.ImageProcess.Url, "application/json", strings.NewReader(string(postMapB))) | ||||||
| 	result, err := http.Post(l.svcCtx.Config.BLMService.ImageProcess.Url, contentType, strings.NewReader(string(postMapB))) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logx.Error(err) | 		logx.Error(err) | ||||||
| 		return resp.SetStatus(basic.CodeFileUploadLogoErr, "service fail") | 		return resp.SetStatus(basic.CodeFileUploadLogoErr, "service fail") | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								server_api/resource.api
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								server_api/resource.api
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | syntax = "v1" | ||||||
|  | 
 | ||||||
|  | info ( | ||||||
|  | 	title: // TODO: add title | ||||||
|  | 	desc: // TODO: add description | ||||||
|  | 	author: "" | ||||||
|  | 	email: "" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | import "basic.api" | ||||||
|  | 
 | ||||||
|  | service resource { | ||||||
|  | 	@handler LogoCombineHandler | ||||||
|  | 	post /api/resource/logo-combine(LogoCombineReq) returns (response); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type ( | ||||||
|  | 	LogoCombineReq { | ||||||
|  | 		ResourceKey  string `form:"resource_key"`  // 资源唯一标识 | ||||||
|  | 		CombineParam string `form:"combine_param"` // 合图参数 | ||||||
|  | 		TemplateId   int64  `form:"template_id"`   // 合图参数 | ||||||
|  | 	} | ||||||
|  | ) | ||||||
| @ -77,8 +77,9 @@ var ( | |||||||
| 	CodeAesCbcEncryptionErr = &StatusResponse{5106, "encryption data err"} // 加密数据失败 | 	CodeAesCbcEncryptionErr = &StatusResponse{5106, "encryption data err"} // 加密数据失败 | ||||||
| 	CodeAesCbcDecryptionErr = &StatusResponse{5107, "decryption data err"} // 解密数据失败 | 	CodeAesCbcDecryptionErr = &StatusResponse{5107, "decryption data err"} // 解密数据失败 | ||||||
| 
 | 
 | ||||||
| 	CodeFileUploadErr     = &StatusResponse{5110, "file upload  err"} // 文件上传失败 | 	CodeFileUploadErr      = &StatusResponse{5110, "file upload  err"} // 文件上传失败 | ||||||
| 	CodeFileUploadLogoErr = &StatusResponse{5111, "logo upload  err"} // 用户上传LOGO失败 | 	CodeFileUploadLogoErr  = &StatusResponse{5111, "logo upload  err"} // 用户上传LOGO失败 | ||||||
|  | 	CodeFileLogoCombineErr = &StatusResponse{5112, "logo upload  err"} // 用户合图失败 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type Response struct { | type Response struct { | ||||||
|  | |||||||
							
								
								
									
										127
									
								
								utils/file/upload.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								utils/file/upload.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,127 @@ | |||||||
|  | package file | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"fusenapi/model/gmodel" | ||||||
|  | 	"fusenapi/utils/basic" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"github.com/aws/aws-sdk-go/aws" | ||||||
|  | 	"github.com/aws/aws-sdk-go/aws/request" | ||||||
|  | 	"github.com/aws/aws-sdk-go/aws/session" | ||||||
|  | 	"github.com/aws/aws-sdk-go/service/s3" | ||||||
|  | 	"github.com/zeromicro/go-zero/core/logx" | ||||||
|  | 	"gorm.io/gorm" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type Upload struct { | ||||||
|  | 	Ctx        context.Context | ||||||
|  | 	MysqlConn  *gorm.DB | ||||||
|  | 	AwsSession *session.Session | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type UploadBaseReq struct { | ||||||
|  | 	FileHash     string | ||||||
|  | 	FileData     string | ||||||
|  | 	Metadata     string | ||||||
|  | 	UploadBucket int64 | ||||||
|  | 	ApiType      int64 | ||||||
|  | 	UserId       int64 | ||||||
|  | 	GuestId      int64 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type UploadBaseRes struct { | ||||||
|  | 	Key          string `json:"key"` | ||||||
|  | 	Status       int64  `json:"status"` | ||||||
|  | 	ApiType      int64  `json:"api_type"` | ||||||
|  | 	ResourceId   string `json:"resource_id"` | ||||||
|  | 	ResourceType string `json:"resource_type"` | ||||||
|  | 	ResourceUrl  string `json:"resource_url"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (upload *Upload) UploadFileByBase64(req *UploadBaseReq) (*UploadBaseRes, error) { | ||||||
|  | 	// 定义存储桶名称 | ||||||
|  | 	var bucketName *string | ||||||
|  | 	var apiType int64 = req.ApiType | ||||||
|  | 
 | ||||||
|  | 	// 根据类别选择存储桶 | ||||||
|  | 	switch req.UploadBucket { | ||||||
|  | 	case 2: | ||||||
|  | 		bucketName = basic.TempfileBucketName | ||||||
|  | 	default: | ||||||
|  | 		bucketName = basic.StorageBucketName | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// 设置AWS会话的区域 | ||||||
|  | 	upload.AwsSession.Config.Region = aws.String("us-west-1") | ||||||
|  | 
 | ||||||
|  | 	// 创建新的S3服务实例 | ||||||
|  | 	svc := s3.New(upload.AwsSession) | ||||||
|  | 
 | ||||||
|  | 	// 定义S3请求和当前时间 | ||||||
|  | 	var s3req *request.Request | ||||||
|  | 
 | ||||||
|  | 	var resourceId string = req.FileHash | ||||||
|  | 
 | ||||||
|  | 	var uploadBaseRes = UploadBaseRes{} | ||||||
|  | 	resourceModel := gmodel.NewFsResourceModel(upload.MysqlConn) | ||||||
|  | 	resourceInfo, err := resourceModel.FindOneById(upload.Ctx, resourceId) | ||||||
|  | 	if err == nil && resourceInfo.ResourceId != "" { | ||||||
|  | 		uploadBaseRes.Status = 1 | ||||||
|  | 		uploadBaseRes.ResourceId = resourceId | ||||||
|  | 		uploadBaseRes.ResourceUrl = *resourceInfo.ResourceUrl | ||||||
|  | 	} else { | ||||||
|  | 		dist, contentType, err := FileBase64ToByte(req.FileData) | ||||||
|  | 
 | ||||||
|  | 		if err != nil { | ||||||
|  | 			logx.Errorf("err:%+v,desc:%+v", err, "fail.upload.resourceInfoGet.mysql") | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// 创建S3对象存储请求 | ||||||
|  | 		s3req, _ = svc.PutObjectRequest( | ||||||
|  | 			&s3.PutObjectInput{ | ||||||
|  | 				Bucket: bucketName, | ||||||
|  | 				Key:    &resourceId, | ||||||
|  | 			}, | ||||||
|  | 		) | ||||||
|  | 
 | ||||||
|  | 		// 设置请求体为文件数据 | ||||||
|  | 		s3req.SetBufferBody(dist) | ||||||
|  | 
 | ||||||
|  | 		// 发送请求 | ||||||
|  | 		err = s3req.Send() | ||||||
|  | 
 | ||||||
|  | 		// 检查是否有错误 | ||||||
|  | 		if err != nil { | ||||||
|  | 			logx.Errorf("err:%+v,desc:%+v", err, "fail.upload.s3req") | ||||||
|  | 			return nil, err | ||||||
|  | 		} else { | ||||||
|  | 			var url = s3req.HTTPRequest.URL.String() | ||||||
|  | 			// 打印请求URL | ||||||
|  | 			logx.Info(url) | ||||||
|  | 			uploadBaseRes.Status = 1 | ||||||
|  | 			uploadBaseRes.ResourceId = resourceId | ||||||
|  | 			uploadBaseRes.ResourceUrl = url | ||||||
|  | 			var version string = "0.0.1" | ||||||
|  | 			var nowTime = time.Now() | ||||||
|  | 			_, err = resourceModel.Create(upload.Ctx, &gmodel.FsResource{ | ||||||
|  | 				ResourceId:   resourceId, | ||||||
|  | 				UserId:       &req.UserId, | ||||||
|  | 				GuestId:      &req.GuestId, | ||||||
|  | 				ResourceType: &contentType, | ||||||
|  | 				ResourceUrl:  &url, | ||||||
|  | 				Version:      &version, | ||||||
|  | 				UploadedAt:   &nowTime, | ||||||
|  | 				Metadata:     &req.Metadata, | ||||||
|  | 				ApiType:      &apiType, | ||||||
|  | 				BucketName:   bucketName, | ||||||
|  | 			}) | ||||||
|  | 			if err != nil { | ||||||
|  | 				logx.Errorf("err:%+v,desc:%+v", err, "fail.upload.resourceInfoAdd.mysql") | ||||||
|  | 				return nil, err | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return &uploadBaseRes, err | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user