初始化
This commit is contained in:
203
server/service/share_service.go
Normal file
203
server/service/share_service.go
Normal file
@@ -0,0 +1,203 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"seeyon-filesystem/config"
|
||||
"seeyon-filesystem/dto"
|
||||
"seeyon-filesystem/model"
|
||||
"seeyon-filesystem/repository"
|
||||
"seeyon-filesystem/storage"
|
||||
"seeyon-filesystem/utils"
|
||||
)
|
||||
|
||||
// ShareService 分享业务服务
|
||||
type ShareService struct {
|
||||
shareRepo *repository.ShareRepository
|
||||
fileRepo *repository.FileRepository
|
||||
}
|
||||
|
||||
// NewShareService 创建分享服务实例
|
||||
func NewShareService() *ShareService {
|
||||
return &ShareService{
|
||||
shareRepo: repository.NewShareRepository(),
|
||||
fileRepo: repository.NewFileRepository(),
|
||||
}
|
||||
}
|
||||
|
||||
// Create 创建分享链接
|
||||
func (s *ShareService) Create(req *dto.ShareCreateRequest, ownerID uint64) (*dto.ShareVO, error) {
|
||||
// 验证文件存在
|
||||
file, err := s.fileRepo.FindByID(req.FileID)
|
||||
if err != nil {
|
||||
return nil, errors.New("文件不存在")
|
||||
}
|
||||
if file.OwnerID != ownerID {
|
||||
return nil, errors.New("无权分享此文件")
|
||||
}
|
||||
|
||||
// 生成分享码
|
||||
shareCode, err := generateShareCode()
|
||||
if err != nil {
|
||||
return nil, errors.New("生成分享码失败")
|
||||
}
|
||||
|
||||
share := &model.Share{
|
||||
FileID: req.FileID,
|
||||
OwnerID: ownerID,
|
||||
ShareCode: shareCode,
|
||||
AllowPreview: 1,
|
||||
AllowDownload: 1,
|
||||
Status: 1,
|
||||
}
|
||||
|
||||
// 设置密码
|
||||
if req.Password != "" {
|
||||
hashed, _ := utils.HashPassword(req.Password)
|
||||
share.Password = hashed
|
||||
}
|
||||
|
||||
// 设置过期时间
|
||||
if req.ExpireHours > 0 {
|
||||
expireAt := time.Now().Add(time.Duration(req.ExpireHours) * time.Hour)
|
||||
share.ExpireAt = &expireAt
|
||||
}
|
||||
|
||||
share.MaxDownload = req.MaxDownload
|
||||
|
||||
// 设置权限
|
||||
share.AllowPreview = int8(req.AllowPreview)
|
||||
share.AllowDownload = int8(req.AllowDownload)
|
||||
// 如果都是0(未传), 默认允许
|
||||
if share.AllowPreview == 0 && share.AllowDownload == 0 {
|
||||
share.AllowPreview = 1
|
||||
share.AllowDownload = 1
|
||||
}
|
||||
|
||||
if err := s.shareRepo.Create(share); err != nil {
|
||||
return nil, errors.New("创建分享失败")
|
||||
}
|
||||
|
||||
return s.toShareVO(share), nil
|
||||
}
|
||||
|
||||
// GetByCode 通过分享码获取分享信息(公开访问)
|
||||
func (s *ShareService) GetByCode(code string) (*dto.ShareFileVO, *model.Share, error) {
|
||||
share, err := s.shareRepo.FindByShareCode(code)
|
||||
if err != nil {
|
||||
return nil, nil, errors.New("分享链接不存在或已失效")
|
||||
}
|
||||
|
||||
// 检查过期
|
||||
if share.ExpireAt != nil && share.ExpireAt.Before(time.Now()) {
|
||||
return nil, nil, errors.New("分享链接已过期")
|
||||
}
|
||||
|
||||
// 检查下载次数
|
||||
if share.MaxDownload > 0 && share.DownloadCount >= share.MaxDownload {
|
||||
return nil, nil, errors.New("下载次数已达上限")
|
||||
}
|
||||
|
||||
// 获取文件信息
|
||||
file, err := s.fileRepo.FindByID(share.FileID)
|
||||
if err != nil {
|
||||
return nil, nil, errors.New("文件不存在")
|
||||
}
|
||||
|
||||
// 生成预览URL
|
||||
previewURL := ""
|
||||
if share.AllowPreview == 1 && file.StorageKey != "" {
|
||||
engine, err := storage.GetEngineByPolicyID(file.StoragePolicyID)
|
||||
if err == nil {
|
||||
if localEngine, ok := engine.(*storage.LocalEngine); ok {
|
||||
previewURL = localEngine.GetURL(file.StorageKey)
|
||||
} else if minioEngine, ok := engine.(*storage.MinIOEngine); ok {
|
||||
previewURL = minioEngine.GetPreviewURL(file.StorageKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileVO := &dto.ShareFileVO{
|
||||
Name: file.Name,
|
||||
Extension: file.Extension,
|
||||
Size: file.Size,
|
||||
MimeType: file.MimeType,
|
||||
PreviewURL: previewURL,
|
||||
AllowPreview: share.AllowPreview == 1,
|
||||
AllowDownload: share.AllowDownload == 1,
|
||||
CreatedAt: file.CreatedAt,
|
||||
}
|
||||
|
||||
return fileVO, share, nil
|
||||
}
|
||||
|
||||
// VerifyPassword 验证分享密码
|
||||
func (s *ShareService) VerifyPassword(shareID uint64, password string) bool {
|
||||
share, err := s.shareRepo.FindByID(shareID)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return utils.CheckPassword(password, share.Password)
|
||||
}
|
||||
|
||||
// ListByOwner 查询用户的分享列表
|
||||
func (s *ShareService) ListByOwner(ownerID uint64) ([]dto.ShareVO, error) {
|
||||
shares, err := s.shareRepo.ListByOwner(ownerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vos := make([]dto.ShareVO, 0, len(shares))
|
||||
for i := range shares {
|
||||
vos = append(vos, *s.toShareVO(&shares[i]))
|
||||
}
|
||||
return vos, nil
|
||||
}
|
||||
|
||||
// Cancel 取消分享
|
||||
func (s *ShareService) Cancel(id uint64, ownerID uint64) error {
|
||||
share, err := s.shareRepo.FindByID(id)
|
||||
if err != nil {
|
||||
return errors.New("分享不存在")
|
||||
}
|
||||
if share.OwnerID != ownerID {
|
||||
return errors.New("无权操作此分享")
|
||||
}
|
||||
return s.shareRepo.Cancel(id)
|
||||
}
|
||||
|
||||
// toShareVO 转换为视图对象
|
||||
func (s *ShareService) toShareVO(share *model.Share) *dto.ShareVO {
|
||||
// 生成完整分享链接
|
||||
publicURL := config.AppConfig.Server.PublicURL
|
||||
if publicURL == "" {
|
||||
publicURL = "http://localhost:8080"
|
||||
}
|
||||
publicURL = strings.TrimRight(publicURL, "/")
|
||||
|
||||
return &dto.ShareVO{
|
||||
ID: share.ID,
|
||||
ShareCode: share.ShareCode,
|
||||
ShareURL: publicURL + "/s/" + share.ShareCode,
|
||||
HasPassword: share.Password != "",
|
||||
ExpireAt: share.ExpireAt,
|
||||
MaxDownload: share.MaxDownload,
|
||||
DownloadCount: share.DownloadCount,
|
||||
AllowPreview: share.AllowPreview,
|
||||
AllowDownload: share.AllowDownload,
|
||||
CreatedAt: share.CreatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
// generateShareCode 生成8字节随机分享码(16位十六进制字符串)
|
||||
func generateShareCode() (string, error) {
|
||||
bytes := make([]byte, 8)
|
||||
if _, err := rand.Read(bytes); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return hex.EncodeToString(bytes), nil
|
||||
}
|
||||
Reference in New Issue
Block a user