package service import ( "context" "fmt" "oss/consts" "oss/dao" "oss/minio" "oss/model/dto" "oss/model/entity" "time" "github.com/gogf/gf/v2/os/glog" "gitea.com/red-future/common/utils" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/util/gconv" ) type file struct{} // File 存储文件服务 var File = new(file) func (f *file) DownloadToFile(ctx context.Context, req *dto.DownloadToFileReq) (err error) { return minio.DownloadToFile(ctx, req.FileURL, req.LocalPath) } func (f *file) UploadFile(ctx context.Context, req *dto.UploadFileReq) (res *dto.UploadFileRes, err error) { fileSize := gconv.Int(req.File.Size) totalFileSize := 0 // 获取租户id user, err := utils.GetUserInfo(ctx) if err != nil { glog.Errorf(ctx, "获取用户信息失败: %v", err) return } tenantId := user.TenantId // 获取redis-租户存储容量总数key tenantOssTotalKey := fmt.Sprintf(consts.TenantOssTotalKey, gconv.String(user.TenantId)) // 获取redis-租户存储-锁key fileLockKey := fmt.Sprintf(consts.FileLockKey, gconv.String(user.TenantId)) success, err := utils.Lock(ctx, fileLockKey, gconv.Int64(time.Minute*1), func(ctx context.Context) error { // 获取redis-租户存储容量总数 get, err := g.Redis().Get(ctx, tenantOssTotalKey) if err != nil { glog.Errorf(ctx, "获取redis-租户存储容量总数失败: %v", err) return err } tenantOssTotalEntity := &entity.TenantOssTotal{} if g.IsEmpty(get) { //查询数据库-获取租户存储容量总数 getByTenantIdReq := &dto.GetByTenantIdReq{ TenantId: user.TenantId, } tenantOssTotalRes, err := dao.TenantOssTotal.GetOneByTenantId(ctx, getByTenantIdReq) if err != nil { glog.Errorf(ctx, "查询数据库-获取租户存储容量总数失败: %v", err) return err } if tenantOssTotalRes == nil || g.IsEmpty(tenantOssTotalRes.Id) { // 数据库中没有该租户的记录,创建默认配置 tenantOssTotalEntity.TenantId = user.TenantId tenantOssTotalEntity.UsedOssSize = 0 tenantOssTotalEntity.TotalOssSize = g.Cfg().MustGet(ctx, "oss.capacitySize").Int() * 1024 * 1024 } else { tenantOssTotalEntity = tenantOssTotalRes } } else { // 反序列化-redis获取租户存储容量总数 if err = gconv.Struct(get, tenantOssTotalEntity); err != nil { glog.Errorf(ctx, "反序列化-redis获取租户存储容量总数失败: %v", err) return err } } tenantId = tenantOssTotalEntity.TenantId fileSize = tenantOssTotalEntity.UsedOssSize + fileSize totalFileSize = tenantOssTotalEntity.TotalOssSize // 设置redis-租户存储容量总数 tenantOssTotalKeyMap := dto.UpdateUsedOssReq{ TenantId: tenantId, UsedOssSize: fileSize, TotalOssSize: totalFileSize, Creator: user.UserName, Updater: user.UserName, } // 修改redis-租户存储容量总数 超时时间10分钟 if err = g.Redis().SetEX(ctx, tenantOssTotalKey, tenantOssTotalKeyMap, gconv.Int64(time.Minute*10)); err != nil { glog.Errorf(ctx, "修改redis-租户存储容量总数 超时时间10分钟失败: %v", err) return err } if fileSize > totalFileSize { return gerror.New("存储服务内存不足") } return nil }) if err != nil { return nil, err } if !success { return nil, gerror.New("存储服务内存不足") } // 上传图片 var fileURL, fileName, fileFormat string fileURL, fileName, fileFormat, err = minio.UploadFile(ctx, req.File) if err != nil { glog.Errorf(ctx, "上传图片失败: %v", err) return nil, err } // 插入数据库 ossEntity := &dto.UploadFile{ TenantId: tenantId, FileURL: fileURL, FileSize: fileSize, } if _, err = dao.File.Insert(ctx, ossEntity); err != nil { return nil, err } // 返回图片url res = &dto.UploadFileRes{ FileURL: fileURL, FileSize: fileSize, FileName: fileName, FileFormat: fileFormat, } url, err := utils.GetFileAddressPrefix(ctx) if err != nil { return } res.FileAddressPrefix = url return } // UploadFileBytes 上传文件(字节流) func (f *file) UploadFileBytes(ctx context.Context, req *dto.UploadFileBytesReq) (res *dto.UploadFileRes, err error) { // 获取用户信息 user, err := utils.GetUserInfo(ctx) if err != nil { glog.Errorf(ctx, "获取用户信息失败: %v", err) return } tenantId := user.TenantId // 上传到 MinIO fileURL, fileFormat, err := minio.UploadFileBytes(ctx, req.FileName, req.FileBytes, req.FileStoreURL) if err != nil { glog.Errorf(ctx, "上传文件失败: %v", err) return nil, err } // 插入数据库记录 ossEntity := &dto.UploadFile{ TenantId: tenantId, FileURL: fileURL, FileSize: len(req.FileBytes), } if _, err = dao.File.Insert(ctx, ossEntity); err != nil { return nil, err } res = &dto.UploadFileRes{ FileURL: fileURL, FileSize: len(req.FileBytes), FileName: req.FileName, FileFormat: fileFormat, } res.FileAddressPrefix, _ = utils.GetFileAddressPrefix(ctx) return }