You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sonic/service/impl/attachment.go

240 lines
8.4 KiB
Go

package impl
import (
"context"
"mime/multipart"
"os"
"strings"
"go.uber.org/zap"
"gorm.io/gorm"
"github.com/go-sonic/sonic/consts"
"github.com/go-sonic/sonic/dal"
"github.com/go-sonic/sonic/log"
"github.com/go-sonic/sonic/model/dto"
"github.com/go-sonic/sonic/model/entity"
"github.com/go-sonic/sonic/model/param"
"github.com/go-sonic/sonic/service"
"github.com/go-sonic/sonic/service/file_storage"
"github.com/go-sonic/sonic/util/xerr"
)
type attachmentServiceImpl struct {
OptionService service.OptionService
FileStorageComposite file_storage.FileStorageComposite
}
func (a *attachmentServiceImpl) ConvertToDTOs(ctx context.Context, attachments []*entity.Attachment) ([]*dto.AttachmentDTO, error) {
dtos := make([]*dto.AttachmentDTO, 0, len(attachments))
for _, attachment := range attachments {
dto := &dto.AttachmentDTO{
ID: attachment.ID,
Name: attachment.Name,
Path: attachment.Path,
FileKey: attachment.FileKey,
ThumbPath: attachment.ThumbPath,
MediaType: attachment.MediaType,
Suffix: attachment.Suffix,
Width: attachment.Width,
Height: attachment.Height,
Size: attachment.Size,
AttachmentType: consts.AttachmentType(attachment.Type),
}
dtos = append(dtos, dto)
path, err := a.FileStorageComposite.GetFileStorage(consts.AttachmentType(attachment.Type)).GetFilePath(ctx, attachment.Path)
if err != nil {
log.CtxError(ctx, "GetFilePath err", zap.Error(err))
}
thumbPath, err := a.FileStorageComposite.GetFileStorage(consts.AttachmentType(attachment.Type)).GetFilePath(ctx, attachment.ThumbPath)
if err != nil {
log.CtxError(ctx, "GetFilePath err", zap.Error(err))
}
dto.Path = path
dto.ThumbPath = thumbPath
}
return dtos, nil
}
func NewAttachmentService(optionService service.OptionService, fileStorageComposite file_storage.FileStorageComposite) service.AttachmentService {
return &attachmentServiceImpl{
FileStorageComposite: fileStorageComposite,
OptionService: optionService,
}
}
func (a *attachmentServiceImpl) ConvertToDTO(ctx context.Context, attachment *entity.Attachment) (*dto.AttachmentDTO, error) {
dto := &dto.AttachmentDTO{
ID: attachment.ID,
Name: attachment.Name,
Path: attachment.Path,
FileKey: attachment.FileKey,
ThumbPath: attachment.ThumbPath,
MediaType: attachment.MediaType,
Suffix: attachment.Suffix,
Width: attachment.Width,
Height: attachment.Height,
Size: attachment.Size,
AttachmentType: consts.AttachmentType(attachment.Type),
}
path, err := a.FileStorageComposite.GetFileStorage(consts.AttachmentType(attachment.Type)).GetFilePath(ctx, attachment.Path)
if err != nil {
return nil, err
}
thumbPath, err := a.FileStorageComposite.GetFileStorage(consts.AttachmentType(attachment.Type)).GetFilePath(ctx, attachment.ThumbPath)
if err != nil {
return nil, err
}
dto.Path = path
dto.ThumbPath = thumbPath
return dto, nil
}
func (a *attachmentServiceImpl) Page(ctx context.Context, queryParam *param.AttachmentQuery) ([]*entity.Attachment, int64, error) {
attachmentDAL := dal.GetQueryByCtx(ctx).Attachment
attachmentDo := attachmentDAL.WithContext(ctx)
if queryParam.Keyword != "" {
attachmentDo = attachmentDo.Where(attachmentDAL.Name.Like(queryParam.Keyword))
}
if queryParam.PageNum >= 0 && queryParam.PageSize >= 0 {
if queryParam.PageSize > 50 {
queryParam.PageSize = 50
}
} else {
queryParam.PageSize = 10
queryParam.PageNum = 0
}
if queryParam.Keyword != "" {
attachmentDo = attachmentDo.Where(attachmentDAL.Name.Like(queryParam.Keyword))
}
if queryParam.AttachmentType != nil {
attachmentDo = attachmentDo.Where(attachmentDAL.Type.Eq(*queryParam.AttachmentType))
}
if queryParam.MediaType != "" {
attachmentDo = attachmentDo.Where(attachmentDAL.MediaType.Eq(queryParam.MediaType))
}
attachments, totalCount, err := attachmentDo.FindByPage(queryParam.PageNum*queryParam.PageSize, queryParam.PageSize)
if err != nil {
return nil, 0, WrapDBErr(err)
}
return attachments, totalCount, nil
}
func (a *attachmentServiceImpl) GetAttachment(ctx context.Context, attachmentID int32) (*entity.Attachment, error) {
attachmentDAL := dal.GetQueryByCtx(ctx).Attachment
attachment, err := attachmentDAL.WithContext(ctx).Where(attachmentDAL.ID.Eq(attachmentID)).Take()
if err != nil {
return nil, WrapDBErr(err)
}
return attachment, nil
}
func (a *attachmentServiceImpl) Upload(ctx context.Context, fileHeader *multipart.FileHeader) (attachmentDTO *dto.AttachmentDTO, err error) {
attachmentType := a.OptionService.GetAttachmentType(ctx)
fileStorage := a.FileStorageComposite.GetFileStorage(attachmentType)
attachmentDAL := dal.GetQueryByCtx(ctx).Attachment
attachmentDTO, err = fileStorage.Upload(ctx, fileHeader)
if err != nil {
return nil, err
}
record, err := attachmentDAL.WithContext(ctx).Where(attachmentDAL.Path.Eq(attachmentDTO.Path)).Take()
if record != nil && err == nil {
return nil, xerr.BadParam.New("附件路径为 " + attachmentDTO.Path + " 已经存在").
WithStatus(xerr.StatusBadRequest).
WithMsg("附件路径为 " + attachmentDTO.Path + " 已经存在")
}
if err != nil && err != gorm.ErrRecordNotFound {
return nil, WrapDBErr(err)
}
attachmentEntity := &entity.Attachment{
FileKey: attachmentDTO.FileKey,
Height: attachmentDTO.Height,
MediaType: attachmentDTO.MediaType,
Name: attachmentDTO.Name,
Path: strings.ReplaceAll(attachmentDTO.Path, string(os.PathSeparator), "/"),
Size: attachmentDTO.Size,
Suffix: attachmentDTO.Suffix,
ThumbPath: attachmentDTO.ThumbPath,
Type: attachmentDTO.AttachmentType,
Width: attachmentDTO.Width,
}
// change file path separator to url separator
if err = attachmentDAL.WithContext(ctx).Create(attachmentEntity); err != nil {
return nil, WrapDBErr(err)
}
attachmentDTO.ID = attachmentEntity.ID
return attachmentDTO, nil
}
func (a *attachmentServiceImpl) Delete(ctx context.Context, attachmentID int32) (*entity.Attachment, error) {
attachmentDAL := dal.GetQueryByCtx(ctx).Attachment
attachment, err := attachmentDAL.WithContext(ctx).Where(attachmentDAL.ID.Eq(attachmentID)).Take()
if err != nil {
return nil, WrapDBErr(err)
}
result, err := attachmentDAL.WithContext(ctx).Where(attachmentDAL.ID.Eq(attachmentID)).Delete()
if err != nil || result.RowsAffected != 1 {
return nil, xerr.WithMsg(err, "delete file failed")
}
fileStorage := a.FileStorageComposite.GetFileStorage(consts.AttachmentType(attachment.Type))
err = fileStorage.Delete(ctx, attachment.FileKey)
if err != nil {
return nil, xerr.WithMsg(err, "delete file failed")
}
return attachment, nil
}
func (a *attachmentServiceImpl) DeleteBatch(ctx context.Context, IDs []int32) (attachments []*entity.Attachment, err error) {
attachments = make([]*entity.Attachment, 0)
var globalErr error
for _, id := range IDs {
attachment, err := a.Delete(ctx, id)
if err != nil {
globalErr = err
} else {
attachments = append(attachments, attachment)
}
}
if globalErr != nil {
return attachments, xerr.NoType.Wrap(err).WithMsg("Failed to delete some files")
}
return attachments, nil
}
func (a *attachmentServiceImpl) Update(ctx context.Context, id int32, updateParam *param.AttachmentUpdate) (*entity.Attachment, error) {
attachmentDAL := dal.GetQueryByCtx(ctx).Attachment
attachment, err := attachmentDAL.WithContext(ctx).Where(attachmentDAL.ID.Eq(id)).Take()
if err != nil {
return nil, WrapDBErr(err)
}
result, err := attachmentDAL.WithContext(ctx).Where(attachmentDAL.ID.Eq(id)).Updates(entity.Attachment{Name: updateParam.Name})
if err != nil {
return nil, WrapDBErr(err)
}
if result.RowsAffected != 1 {
return nil, xerr.NoType.New("update failed")
}
attachment.Name = updateParam.Name
return attachment, nil
}
func (a *attachmentServiceImpl) GetAllMediaTypes(ctx context.Context) ([]string, error) {
attachmentDAL := dal.GetQueryByCtx(ctx).Attachment
var allMediaTypes []string
err := attachmentDAL.WithContext(ctx).Distinct(attachmentDAL.MediaType).Select(attachmentDAL.MediaType).Scan(&allMediaTypes)
return allMediaTypes, WrapDBErr(err)
}
func (a *attachmentServiceImpl) GetAllTypes(ctx context.Context) ([]consts.AttachmentType, error) {
attachmentDAL := dal.GetQueryByCtx(ctx).Attachment
var allTypes []consts.AttachmentType
err := attachmentDAL.WithContext(ctx).Distinct(attachmentDAL.Type).Select(attachmentDAL.Type).Scan(&allTypes)
return allTypes, err
}