2022-09-27 17:59:05 +08:00
|
|
|
package uploader
|
|
|
|
|
|
|
|
import (
|
2022-10-27 18:09:27 +08:00
|
|
|
"bytes"
|
2022-09-27 17:59:05 +08:00
|
|
|
"fmt"
|
2022-10-27 18:09:27 +08:00
|
|
|
"io"
|
2022-10-27 20:27:34 +08:00
|
|
|
"io/ioutil"
|
2022-09-27 17:59:05 +08:00
|
|
|
"mime/multipart"
|
2022-10-27 18:09:27 +08:00
|
|
|
"os"
|
2022-09-27 17:59:05 +08:00
|
|
|
"path"
|
|
|
|
"path/filepath"
|
|
|
|
|
2022-10-24 16:51:05 +08:00
|
|
|
"github.com/answerdev/answer/internal/base/reason"
|
|
|
|
"github.com/answerdev/answer/internal/service/service_config"
|
|
|
|
"github.com/answerdev/answer/pkg/dir"
|
|
|
|
"github.com/answerdev/answer/pkg/uid"
|
2022-10-27 18:09:27 +08:00
|
|
|
"github.com/disintegration/imaging"
|
2022-09-27 17:59:05 +08:00
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/segmentfault/pacman/errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2022-10-27 20:27:34 +08:00
|
|
|
avatarSubPath = "avatar"
|
|
|
|
avatarThumbSubPath = "avatar_thumb"
|
|
|
|
postSubPath = "post"
|
2022-09-27 17:59:05 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
// UploaderService user service
|
|
|
|
type UploaderService struct {
|
|
|
|
serviceConfig *service_config.ServiceConfig
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewUploaderService new upload service
|
|
|
|
func NewUploaderService(serviceConfig *service_config.ServiceConfig) *UploaderService {
|
2022-10-24 20:26:00 +08:00
|
|
|
err := dir.CreateDirIfNotExist(filepath.Join(serviceConfig.UploadPath, avatarSubPath))
|
2022-09-27 17:59:05 +08:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2022-10-24 20:26:00 +08:00
|
|
|
err = dir.CreateDirIfNotExist(filepath.Join(serviceConfig.UploadPath, postSubPath))
|
2022-09-27 17:59:05 +08:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return &UploaderService{
|
|
|
|
serviceConfig: serviceConfig,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (us *UploaderService) UploadAvatarFile(ctx *gin.Context, file *multipart.FileHeader, fileExt string) (
|
|
|
|
url string, err error) {
|
|
|
|
newFilename := fmt.Sprintf("%s%s", uid.IDStr12(), fileExt)
|
|
|
|
avatarFilePath := path.Join(avatarSubPath, newFilename)
|
|
|
|
return us.uploadFile(ctx, file, avatarFilePath)
|
|
|
|
}
|
|
|
|
|
2022-10-27 20:27:34 +08:00
|
|
|
func (us *UploaderService) AvatarThumbFile(ctx *gin.Context, uploadPath, fileName string, w, h int) (
|
|
|
|
avatarfile []byte, err error) {
|
|
|
|
thumbFileName := fmt.Sprintf("%d_%d@%s", w, h, fileName)
|
|
|
|
thumbfilePath := fmt.Sprintf("%s/%s/%s", uploadPath, avatarThumbSubPath, thumbFileName)
|
|
|
|
avatarfile, err = ioutil.ReadFile(thumbfilePath)
|
2022-10-27 18:09:27 +08:00
|
|
|
if err != nil {
|
2022-10-27 20:27:34 +08:00
|
|
|
filePath := fmt.Sprintf("%s/avatar/%s", uploadPath, fileName)
|
|
|
|
avatarfile, err = ioutil.ReadFile(filePath)
|
|
|
|
if err != nil {
|
|
|
|
return avatarfile, err
|
|
|
|
}
|
|
|
|
reader := bytes.NewReader(avatarfile)
|
|
|
|
img, err := imaging.Decode(reader)
|
|
|
|
if err != nil {
|
|
|
|
return avatarfile, err
|
|
|
|
}
|
|
|
|
new_image := imaging.Fill(img, w, h, imaging.Center, imaging.Linear)
|
|
|
|
var buf bytes.Buffer
|
|
|
|
fileSuffix := path.Ext(fileName)
|
|
|
|
formatExts := map[string]imaging.Format{
|
|
|
|
".jpg": imaging.JPEG,
|
|
|
|
".jpeg": imaging.JPEG,
|
|
|
|
".png": imaging.PNG,
|
|
|
|
".gif": imaging.GIF,
|
|
|
|
".tif": imaging.TIFF,
|
|
|
|
".tiff": imaging.TIFF,
|
|
|
|
".bmp": imaging.BMP,
|
|
|
|
}
|
|
|
|
_, ok := formatExts[fileSuffix]
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
return avatarfile, fmt.Errorf("img extension not exist")
|
|
|
|
}
|
|
|
|
err = imaging.Encode(&buf, new_image, formatExts[fileSuffix])
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return avatarfile, err
|
|
|
|
}
|
|
|
|
thumbReader := bytes.NewReader(buf.Bytes())
|
|
|
|
dir.CreateDirIfNotExist(path.Join(us.serviceConfig.UploadPath, avatarThumbSubPath))
|
|
|
|
avatarFilePath := path.Join(avatarThumbSubPath, thumbFileName)
|
|
|
|
savefilePath := path.Join(us.serviceConfig.UploadPath, avatarFilePath)
|
|
|
|
out, err := os.Create(savefilePath)
|
|
|
|
if err != nil {
|
|
|
|
return avatarfile, err
|
|
|
|
}
|
|
|
|
defer out.Close()
|
|
|
|
_, err = io.Copy(out, thumbReader)
|
|
|
|
if err != nil {
|
|
|
|
return avatarfile, err
|
|
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
2022-10-27 18:09:27 +08:00
|
|
|
}
|
2022-10-27 20:27:34 +08:00
|
|
|
// thumb file exist
|
|
|
|
return avatarfile, nil
|
|
|
|
|
2022-10-27 18:09:27 +08:00
|
|
|
}
|
|
|
|
|
2022-09-27 17:59:05 +08:00
|
|
|
func (us *UploaderService) UploadPostFile(ctx *gin.Context, file *multipart.FileHeader, fileExt string) (
|
|
|
|
url string, err error) {
|
|
|
|
newFilename := fmt.Sprintf("%s%s", uid.IDStr12(), fileExt)
|
|
|
|
avatarFilePath := path.Join(postSubPath, newFilename)
|
|
|
|
return us.uploadFile(ctx, file, avatarFilePath)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (us *UploaderService) uploadFile(ctx *gin.Context, file *multipart.FileHeader, fileSubPath string) (
|
|
|
|
url string, err error) {
|
|
|
|
filePath := path.Join(us.serviceConfig.UploadPath, fileSubPath)
|
|
|
|
if err := ctx.SaveUploadedFile(file, filePath); err != nil {
|
|
|
|
return "", errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
|
|
|
|
}
|
|
|
|
url = fmt.Sprintf("%s/uploads/%s", us.serviceConfig.WebHost, fileSubPath)
|
|
|
|
return url, nil
|
|
|
|
}
|