mirror of https://github.com/rocboss/paopao-ce
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
255 lines
6.2 KiB
255 lines
6.2 KiB
2 years ago
|
// Copyright 2022 ROC. All rights reserved.
|
||
|
// Use of this source code is governed by a MIT style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
3 years ago
|
package api
|
||
|
|
||
|
import (
|
||
|
"image"
|
||
|
|
||
|
"github.com/disintegration/imaging"
|
||
|
"github.com/gin-gonic/gin"
|
||
|
"github.com/gofrs/uuid"
|
||
2 years ago
|
"github.com/rocboss/paopao-ce/internal/core"
|
||
|
"github.com/rocboss/paopao-ce/internal/servants/web/broker"
|
||
3 years ago
|
"github.com/rocboss/paopao-ce/pkg/app"
|
||
|
"github.com/rocboss/paopao-ce/pkg/convert"
|
||
|
"github.com/rocboss/paopao-ce/pkg/errcode"
|
||
2 years ago
|
"github.com/sirupsen/logrus"
|
||
3 years ago
|
)
|
||
|
|
||
2 years ago
|
var uploadAttachmentTypeMap = map[string]core.AttachmentType{
|
||
|
"public/image": core.AttachmentTypeImage,
|
||
|
"public/avatar": core.AttachmentTypeImage,
|
||
|
"public/video": core.AttachmentTypeVideo,
|
||
|
"attachment": core.AttachmentTypeOther,
|
||
2 years ago
|
}
|
||
|
|
||
3 years ago
|
func GeneratePath(s string) string {
|
||
|
n := len(s)
|
||
|
if n <= 2 {
|
||
|
return s
|
||
|
}
|
||
|
|
||
|
return GeneratePath(s[:n-2]) + "/" + s[n-2:]
|
||
|
}
|
||
|
|
||
|
func GetFileExt(s string) (string, error) {
|
||
|
switch s {
|
||
|
case "image/png":
|
||
|
return ".png", nil
|
||
|
case "image/jpg":
|
||
|
return ".jpg", nil
|
||
|
case "image/jpeg":
|
||
|
return ".jpeg", nil
|
||
|
case "image/gif":
|
||
|
return ".gif", nil
|
||
|
case "video/mp4":
|
||
|
return ".mp4", nil
|
||
|
case "video/quicktime":
|
||
|
return ".mov", nil
|
||
|
case "application/zip":
|
||
|
return ".zip", nil
|
||
|
default:
|
||
|
return "", errcode.FileInvalidExt.WithDetails("仅允许 png/jpg/gif/mp4/mov/zip 类型")
|
||
|
}
|
||
|
}
|
||
|
func GetImageSize(img image.Rectangle) (int, int) {
|
||
|
b := img.Bounds()
|
||
|
width := b.Max.X
|
||
|
height := b.Max.Y
|
||
|
return width, height
|
||
|
}
|
||
|
|
||
3 years ago
|
func fileCheck(uploadType string, size int64) error {
|
||
|
if uploadType != "public/video" &&
|
||
|
uploadType != "public/image" &&
|
||
|
uploadType != "public/avatar" &&
|
||
|
uploadType != "attachment" {
|
||
|
return errcode.InvalidParams
|
||
|
}
|
||
|
|
||
|
if size > 1024*1024*100 {
|
||
|
return errcode.FileInvalidSize.WithDetails("最大允许100MB")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
3 years ago
|
func UploadAttachment(c *gin.Context) {
|
||
|
response := app.NewResponse(c)
|
||
|
|
||
|
uploadType := c.Request.FormValue("type")
|
||
|
file, fileHeader, err := c.Request.FormFile("file")
|
||
|
if err != nil {
|
||
2 years ago
|
logrus.Errorf("api.UploadAttachment err: %v", err)
|
||
3 years ago
|
response.ToErrorResponse(errcode.FileUploadFailed)
|
||
|
return
|
||
|
}
|
||
|
defer file.Close()
|
||
|
|
||
3 years ago
|
if err = fileCheck(uploadType, fileHeader.Size); err != nil {
|
||
|
cErr, _ := err.(*errcode.Error)
|
||
|
response.ToErrorResponse(cErr)
|
||
3 years ago
|
return
|
||
|
}
|
||
|
|
||
2 years ago
|
contentType := fileHeader.Header.Get("Content-Type")
|
||
3 years ago
|
fileExt, err := GetFileExt(fileHeader.Header.Get("Content-Type"))
|
||
|
if err != nil {
|
||
2 years ago
|
logrus.Errorf("GetFileExt err: %v", err)
|
||
3 years ago
|
response.ToErrorResponse(err.(*errcode.Error))
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// 生成随机路径
|
||
|
randomPath := uuid.Must(uuid.NewV4()).String()
|
||
|
ossSavePath := uploadType + "/" + GeneratePath(randomPath[:8]) + "/" + randomPath[9:] + fileExt
|
||
|
|
||
2 years ago
|
objectUrl, err := objectStorage.PutObject(ossSavePath, file, fileHeader.Size, contentType, false)
|
||
3 years ago
|
if err != nil {
|
||
2 years ago
|
logrus.Errorf("putObject err: %v", err)
|
||
3 years ago
|
response.ToErrorResponse(errcode.FileUploadFailed)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// 构造附件Model
|
||
2 years ago
|
attachment := &core.Attachment{
|
||
3 years ago
|
FileSize: fileHeader.Size,
|
||
2 years ago
|
Content: objectUrl,
|
||
3 years ago
|
}
|
||
|
|
||
|
if userID, exists := c.Get("UID"); exists {
|
||
|
attachment.UserID = userID.(int64)
|
||
|
}
|
||
|
|
||
3 years ago
|
attachment.Type = uploadAttachmentTypeMap[uploadType]
|
||
2 years ago
|
if attachment.Type == core.AttachmentTypeImage {
|
||
3 years ago
|
var src image.Image
|
||
|
src, err = imaging.Decode(file)
|
||
3 years ago
|
if err == nil {
|
||
|
attachment.ImgWidth, attachment.ImgHeight = GetImageSize(src.Bounds())
|
||
|
}
|
||
|
}
|
||
|
|
||
2 years ago
|
attachment, err = broker.CreateAttachment(attachment)
|
||
3 years ago
|
if err != nil {
|
||
2 years ago
|
logrus.Errorf("service.CreateAttachment err: %v", err)
|
||
3 years ago
|
response.ToErrorResponse(errcode.FileUploadFailed)
|
||
|
}
|
||
|
|
||
|
response.ToResponse(attachment)
|
||
|
}
|
||
|
|
||
|
func DownloadAttachmentPrecheck(c *gin.Context) {
|
||
|
response := app.NewResponse(c)
|
||
|
|
||
|
contentID := convert.StrTo(c.Query("id")).MustInt64()
|
||
|
// 加载content
|
||
2 years ago
|
content, err := broker.GetPostContentByID(contentID)
|
||
3 years ago
|
if err != nil {
|
||
2 years ago
|
logrus.Errorf("service.GetPostContentByID err: %v", err)
|
||
3 years ago
|
response.ToErrorResponse(errcode.InvalidDownloadReq)
|
||
|
}
|
||
|
user, _ := c.Get("USER")
|
||
2 years ago
|
if content.Type == core.ContentTypeChargeAttachment {
|
||
3 years ago
|
// 加载post
|
||
2 years ago
|
post, err := broker.GetPost(content.PostID)
|
||
3 years ago
|
if err != nil {
|
||
2 years ago
|
logrus.Errorf("service.GetPost err: %v", err)
|
||
3 years ago
|
response.ToResponse(gin.H{
|
||
|
"paid": false,
|
||
|
})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// 发布者或管理员免费下载
|
||
2 years ago
|
if post.UserID == user.(*core.User).ID || user.(*core.User).IsAdmin {
|
||
3 years ago
|
response.ToResponse(gin.H{
|
||
|
"paid": true,
|
||
|
})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// 检测是否有购买记录
|
||
|
response.ToResponse(gin.H{
|
||
2 years ago
|
"paid": broker.CheckPostAttachmentIsPaid(post.ID, user.(*core.User).ID),
|
||
3 years ago
|
})
|
||
|
return
|
||
|
}
|
||
|
response.ToResponse(gin.H{
|
||
|
"paid": false,
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func DownloadAttachment(c *gin.Context) {
|
||
|
response := app.NewResponse(c)
|
||
|
|
||
|
contentID := convert.StrTo(c.Query("id")).MustInt64()
|
||
|
|
||
|
// 加载content
|
||
2 years ago
|
content, err := broker.GetPostContentByID(contentID)
|
||
3 years ago
|
if err != nil {
|
||
2 years ago
|
logrus.Errorf("service.GetPostContentByID err: %v", err)
|
||
3 years ago
|
response.ToErrorResponse(errcode.InvalidDownloadReq)
|
||
|
}
|
||
|
|
||
|
// 收费附件
|
||
2 years ago
|
if content.Type == core.ContentTypeChargeAttachment {
|
||
3 years ago
|
user, _ := c.Get("USER")
|
||
|
|
||
|
// 加载post
|
||
2 years ago
|
post, err := broker.GetPost(content.PostID)
|
||
3 years ago
|
if err != nil {
|
||
2 years ago
|
logrus.Errorf("service.GetPost err: %v", err)
|
||
3 years ago
|
response.ToResponse(gin.H{
|
||
|
"paid": false,
|
||
|
})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
paidFlag := false
|
||
|
|
||
|
// 发布者或管理员免费下载
|
||
2 years ago
|
if post.UserID == user.(*core.User).ID || user.(*core.User).IsAdmin {
|
||
3 years ago
|
paidFlag = true
|
||
|
}
|
||
|
|
||
|
// 检测是否有购买记录
|
||
2 years ago
|
if broker.CheckPostAttachmentIsPaid(post.ID, user.(*core.User).ID) {
|
||
3 years ago
|
paidFlag = true
|
||
|
}
|
||
|
|
||
|
if !paidFlag {
|
||
|
// 未购买,则尝试购买
|
||
2 years ago
|
err := broker.BuyPostAttachment(&core.Post{
|
||
|
Model: &core.Model{
|
||
3 years ago
|
ID: post.ID,
|
||
|
},
|
||
|
UserID: post.UserID,
|
||
|
AttachmentPrice: post.AttachmentPrice,
|
||
2 years ago
|
}, user.(*core.User))
|
||
3 years ago
|
if err != nil {
|
||
2 years ago
|
logrus.Errorf("service.BuyPostAttachment err: %v", err)
|
||
3 years ago
|
if err == errcode.InsuffientDownloadMoney {
|
||
|
|
||
|
response.ToErrorResponse(errcode.InsuffientDownloadMoney)
|
||
|
} else {
|
||
|
|
||
|
response.ToErrorResponse(errcode.DownloadExecFail)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
2 years ago
|
objectKey := objectStorage.ObjectKey(content.Content)
|
||
|
signedURL, err := objectStorage.SignURL(objectKey, 60)
|
||
3 years ago
|
if err != nil {
|
||
2 years ago
|
logrus.Errorf("client.SignURL err: %v", err)
|
||
3 years ago
|
response.ToErrorResponse(errcode.DownloadReqError)
|
||
|
return
|
||
|
}
|
||
2 years ago
|
response.ToResponse(signedURL)
|
||
3 years ago
|
}
|