| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- // Code scaffolded by goctl. Safe to edit.
- // goctl 1.10.1
- package minio
- import (
- "context"
- "crypto/md5"
- "encoding/hex"
- "fmt"
- "io"
- "mime/multipart"
- "path/filepath"
- "slices"
- "strings"
- "time"
- "perms-system-server/internal/response"
- "perms-system-server/internal/svc"
- miniogo "github.com/minio/minio-go/v7"
- "github.com/zeromicro/go-zero/core/logx"
- )
- type MinioUploadResult struct {
- Url string `json:"url"`
- Path string `json:"path"`
- Md5 string `json:"md5"`
- Size int64 `json:"size"`
- }
- type MinioUploadLogic struct {
- logx.Logger
- ctx context.Context
- svcCtx *svc.ServiceContext
- }
- func NewMinioUploadLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MinioUploadLogic {
- return &MinioUploadLogic{
- Logger: logx.WithContext(ctx),
- ctx: ctx,
- svcCtx: svcCtx,
- }
- }
- func (l *MinioUploadLogic) MinioUpload(fileHeader *multipart.FileHeader, file multipart.File, fileType string) (*MinioUploadResult, error) {
- if fileType == "" {
- return nil, response.ErrBadRequest("fileType is required")
- }
- minioFileType, ok := l.svcCtx.Config.Minio.FileType[fileType]
- if !ok {
- return nil, response.ErrBadRequest("fileType not configured")
- }
- if minioFileType.Bucket == "" {
- return nil, response.ErrBadRequest("bucket not configured")
- }
- contentType := fileHeader.Header.Get("Content-Type")
- if len(minioFileType.AllowedContentTypes) > 0 && minioFileType.AllowedContentTypes[0] != "" && minioFileType.AllowedContentTypes[0] != "*" {
- if !slices.Contains(minioFileType.AllowedContentTypes, contentType) {
- return nil, response.ErrBadRequest("invalid contentType: " + contentType)
- }
- }
- if err := l.ensureBucketExists(minioFileType.Bucket); err != nil {
- return nil, err
- }
- hash := md5.New()
- if _, err := io.Copy(hash, file); err != nil {
- return nil, response.ErrBadRequest("md5 计算失败: " + err.Error())
- }
- fileMd5 := hex.EncodeToString(hash.Sum(nil))
- file.Seek(0, io.SeekStart)
- fileExt := filepath.Ext(fileHeader.Filename)
- dir := strings.TrimSpace(parseDir(minioFileType.Dir))
- if dir != "" {
- dir += "/"
- }
- objectPath := fmt.Sprintf("%s%s%s", dir, fileMd5, fileExt)
- stat, statErr := l.svcCtx.MinioClient.StatObject(l.ctx, minioFileType.Bucket, objectPath, miniogo.StatObjectOptions{})
- if statErr == nil {
- objectFullPath := fmt.Sprintf("%s/%s", minioFileType.Bucket, objectPath)
- return &MinioUploadResult{
- Url: fmt.Sprintf("%s/%s", l.svcCtx.Config.Minio.Domain, objectFullPath),
- Path: objectFullPath,
- Md5: fileMd5,
- Size: stat.Size,
- }, nil
- }
- errCode := miniogo.ToErrorResponse(statErr).Code
- if errCode == "AccessDenied" || errCode == "NoSuchKey" {
- info, err := l.svcCtx.MinioClient.PutObject(l.ctx, minioFileType.Bucket, objectPath, file, fileHeader.Size, miniogo.PutObjectOptions{
- ContentType: contentType,
- })
- if err != nil {
- return nil, err
- }
- objectFullPath := fmt.Sprintf("%s/%s", minioFileType.Bucket, objectPath)
- return &MinioUploadResult{
- Url: fmt.Sprintf("%s/%s", l.svcCtx.Config.Minio.Domain, objectFullPath),
- Path: objectFullPath,
- Md5: fileMd5,
- Size: info.Size,
- }, nil
- }
- return nil, statErr
- }
- func (l *MinioUploadLogic) ensureBucketExists(bucket string) error {
- exists, err := l.svcCtx.MinioClient.BucketExists(l.ctx, bucket)
- if err != nil {
- return err
- }
- if !exists {
- return l.svcCtx.MinioClient.MakeBucket(l.ctx, bucket, miniogo.MakeBucketOptions{})
- }
- return nil
- }
- func parseDir(template string) string {
- now := time.Now()
- r := strings.NewReplacer(
- "{yyyy}", now.Format("2006"),
- "{mm}", now.Format("01"),
- "{dd}", now.Format("02"),
- )
- return r.Replace(template)
- }
|