package service import ( "context" "fmt" "gitee.com/red-future---jilin-g/common/minio" "gitee.com/red-future---jilin-g/common/mongo" "gitee.com/red-future---jilin-g/common/redis" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/util/gconv" "oss/consts" "oss/dao" "oss/model/dto" "oss/model/entity" "time" ) type file struct{} // File 存储文件服务 var File = new(file) func (f *file) UploadFile(ctx context.Context, req *dto.UploadFileReq) (res *dto.UploadFileRes, err error) { tenantId := "" fileSize := req.File.Size totalFileSize := int64(0) // 获取租户id user, err := mongo.GetTenantInfo(ctx) if err != nil { return } // 获取redis-租户存储容量总数key tenantOssTotalKey := fmt.Sprintf(consts.TenantOssTotalKey, gconv.String(user.TenantId)) // 获取redis-租户存储-锁key fileLockKey := fmt.Sprintf(consts.FileLockKey, gconv.String(user.TenantId)) i := 0 LOCK: if ok, err := redis.RedisClient.SetNX(ctx, fileLockKey, fileSize); !ok || err != nil { // 获取锁失败,需要重试 if i < 5 { i++ time.Sleep(5 * time.Millisecond) goto LOCK } } // 设置redis-租户存储-锁key超时时间1分钟 err = redis.RedisClient.SetEX(ctx, fileLockKey, fileSize, gconv.Int64(time.Minute*1)) if err != nil { return nil, err } // 获取redis-租户存储容量总数 get, err := redis.RedisClient.Get(ctx, tenantOssTotalKey) if err != nil { return nil, err } tenantOssTotalEntity := &entity.TenantOssTotal{} if g.IsEmpty(get) { //查询数据库-获取租户存储容量总数 getByTenantIdReq := &dto.GetByTenantIdReq{ TenantId: gconv.String(user.TenantId), } tenantOssTotal, err := TenantOssTotal.GetOneByTenantId(ctx, getByTenantIdReq) if err != nil { return nil, err } if g.IsEmpty(tenantOssTotal) { tenantOssTotalEntity.TenantId = user.TenantId tenantOssTotalEntity.UsedOssSize = int64(0) tenantOssTotalEntity.TotalOssSize = g.Cfg().MustGet(ctx, "oss.capacitySize").Int64() } else { tenantOssTotalEntity = tenantOssTotal.TenantOssTotal } } else { // 反序列化-redis获取租户存储容量总数 err = gconv.Struct(get, tenantOssTotalEntity) if err != nil { return nil, err } } tenantId = gconv.String(tenantOssTotalEntity.TenantId) fileSize = tenantOssTotalEntity.UsedOssSize + fileSize totalFileSize = tenantOssTotalEntity.TotalOssSize // 设置redis-租户存储容量总数 tenantOssTotalKeyMap := map[string]interface{}{"tenantId": tenantId, "UsedOssSize": fileSize, "TotalOssSize": totalFileSize} // 修改redis-租户存储容量总数 超时时间10分钟 err = redis.RedisClient.SetEX(ctx, tenantOssTotalKey, tenantOssTotalKeyMap, gconv.Int64(time.Minute*10)) if err != nil { return nil, err } if fileSize < totalFileSize { // 删除redis-租户存储-锁key _, err = redis.RedisClient.Del(ctx, fileLockKey) if err != nil { return nil, err } } else { return nil, gerror.New("存储服务内存不足") } // 上传图片 fileURL, err := minio.UploadImage(ctx, req.File) if err != nil { return nil, err } // 插入数据库 ossEntity := &entity.File{ FileURL: fileURL, FileSize: fileSize, } err = dao.File.Insert(ctx, ossEntity) if err != nil { return nil, err } // 返回图片url return &dto.UploadFileRes{ FileURL: fileURL, FileAddressPrefix: minio.GetImgAddressPrefix(ctx), }, err }