package logic import ( "bytes" "context" "net/url" "path/filepath" "time" "godemo/file/file" "godemo/file/internal/svc" "github.com/google/uuid" "github.com/minio/minio-go/v7" "github.com/zeromicro/go-zero/core/logx" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) type UploadLogic struct { ctx context.Context svcCtx *svc.ServiceContext logx.Logger } func NewUploadLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UploadLogic { return &UploadLogic{ ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx), } } // 上传文件(图片/头像/壁纸等) func (l *UploadLogic) Upload(in *file.UploadRequest) (*file.UploadResponse, error) { bucketName := "default" if in.Bucket != "" { bucketName = in.Bucket } // 确保 bucket 存在(自动创建) exists, err := l.svcCtx.MinioClient.BucketExists(l.ctx, bucketName) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } if !exists { err := l.svcCtx.MinioClient.MakeBucket(l.ctx, bucketName, minio.MakeBucketOptions{}) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } } // 生成唯一文件名 ext := getFileExtension(in.Filename) newFileName := uuid.New().String() + ext if in.Folder != "" { newFileName = in.Folder + "/" + newFileName } // 上传对象 _, err = l.svcCtx.MinioClient.PutObject(l.ctx, bucketName, newFileName, bytes.NewReader(in.Content), int64(len(in.Content)), minio.PutObjectOptions{ ContentType: in.ContentType, }) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } // 生成预签名 URL(有效期1小时) reqParams := make(url.Values) presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, bucketName, newFileName, time.Hour, reqParams) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } return &file.UploadResponse{ FileId: newFileName, Url: presignedUrl.String(), }, nil } // 获取文件扩展名(默认 .jpg) func getFileExtension(name string) string { ext := filepath.Ext(name) if ext == "" { return ".jpg" } return ext }