feat: 完善移动端会员业务流程
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
package attachments
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.118im.com/im_team/olons_server/internal/config"
|
||||
"git.118im.com/im_team/olons_server/internal/store"
|
||||
)
|
||||
|
||||
const maxImageSize = 5 << 20
|
||||
|
||||
var ErrImageInvalid = errors.New("image attachment invalid")
|
||||
|
||||
type Repository interface {
|
||||
CreateAttachment(context.Context, store.AttachmentCreation) (*store.Attachment, error)
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
repository Repository
|
||||
cfg config.UploadConfig
|
||||
}
|
||||
|
||||
func New(repository Repository, cfg config.UploadConfig) *Service {
|
||||
return &Service{repository: repository, cfg: cfg}
|
||||
}
|
||||
|
||||
func (s *Service) UploadImage(ctx context.Context, memberID int64, name string, reader io.Reader) (*store.Attachment, error) {
|
||||
if s.repository == nil || memberID <= 0 {
|
||||
return nil, ErrImageInvalid
|
||||
}
|
||||
data, err := io.ReadAll(io.LimitReader(reader, maxImageSize+1))
|
||||
if err != nil || len(data) == 0 || len(data) > maxImageSize {
|
||||
return nil, ErrImageInvalid
|
||||
}
|
||||
mimeType := http.DetectContentType(data)
|
||||
extensions := map[string]string{"image/jpeg": ".jpg", "image/png": ".png", "image/webp": ".webp"}
|
||||
ext, ok := extensions[mimeType]
|
||||
if !ok {
|
||||
return nil, ErrImageInvalid
|
||||
}
|
||||
random := make([]byte, 16)
|
||||
if _, err = rand.Read(random); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileName := hex.EncodeToString(random) + ext
|
||||
if err = os.MkdirAll(s.cfg.Dir, 0o750); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
path := filepath.Join(s.cfg.Dir, fileName)
|
||||
if err = os.WriteFile(path, data, 0o640); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
digest := md5.Sum(data)
|
||||
publicPath := strings.TrimRight(s.cfg.PublicPath, "/") + "/" + fileName
|
||||
attachment, err := s.repository.CreateAttachment(ctx, store.AttachmentCreation{
|
||||
MemberID: memberID, Name: filepath.Base(name), MimeType: mimeType, Path: path,
|
||||
URL: publicPath, Size: int64(len(data)), Ext: strings.TrimPrefix(ext, "."), MD5: hex.EncodeToString(digest[:]),
|
||||
})
|
||||
if err != nil {
|
||||
_ = os.Remove(path)
|
||||
return nil, err
|
||||
}
|
||||
return attachment, nil
|
||||
}
|
||||
Reference in New Issue
Block a user