StorageServer/modules/image/image.go

140 lines
3.0 KiB
Go

package image
import (
"errors"
"io"
"mime/multipart"
"os"
"strconv"
"clickandjoin.app/storageserver/modules/config"
"clickandjoin.app/storageserver/modules/utils"
"github.com/google/uuid"
"github.com/h2non/bimg"
"github.com/sirupsen/logrus"
)
// is specified in the form data of the frontend
const FormFileKey = "file"
const MaxAvatarSize = 2 * 1024 * 1024 // 2 MB
// filename len = 36 + dot . 1 + longestFileType 4
// example: cf75ace7-da4c-434d-bf7d-0bdbcea5c57d.webp
const MaxFileNameLen = 41
var validFileTypes = []string{"jpeg", "jpg", "png", "webp"}
// represents the query parameter size for the dynamic image resolution
// example ?size=1 -> 64x64
var ImageSizes = []int{32, 64, 150, 256, 512, 1024}
const DefaultImageSize = 0
func FileTypeVerification(fileType string) bool {
for _, validFileType := range validFileTypes {
if fileType == "image/"+validFileType {
return true
}
}
return false
}
func createUserFolder(userId string) error {
path := config.Cfg.StoragePath + userId
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
err = os.Mkdir(utils.GetUserStoragePath(userId), os.ModePerm)
if err != nil && !errors.Is(err, os.ErrExist) {
logrus.Errorln("Failed to create user folder, err:", err)
return err
}
}
return nil
}
func SaveImage(fileHeader *multipart.FileHeader, userId string) (fileName string, err error) {
err = createUserFolder(userId)
if err != nil {
return "", err
}
f, err := fileHeader.Open()
if err != nil {
logrus.Errorln("Failed to open file header, err:", err)
return "", err
}
fileData, err := io.ReadAll(f)
if err != nil {
logrus.Errorln("Failed to read file, err:", err)
return "", err
}
fileName = uuid.New().String()
newImage := bimg.NewImage(fileData).Image()
err = bimg.Write(utils.GetUserStoragePath(userId)+fileName+".webp", newImage)
if err != nil {
logrus.Errorln("Failed to save image, err:", err)
return "", err
}
return fileName + ".webp", nil
}
func GetImage(userId string, fileName string, imageSize string) ([]byte, error) {
imgSize, err := strconv.Atoi(imageSize)
if err != nil {
imgSize = DefaultImageSize
}
buffer, err := bimg.Read(utils.GetUserStoragePath(userId) + fileName)
if err != nil {
logrus.Errorln("Failed to read image, err:", err)
return []byte{}, err
}
// check that the value has not been manipulated and is greater than the largest index value in the list
if imgSize > len(ImageSizes)-1 {
imgSize = DefaultImageSize
}
resolution := ImageSizes[imgSize]
newImage, err := bimg.NewImage(buffer).ForceResize(resolution, resolution)
if err != nil {
logrus.Errorln("Failed to force resize, err:", err)
return []byte{}, err
}
return newImage, nil
}
func DeleteOldAvatarImage(userId string) error {
path := utils.GetUserStoragePath(userId)
dir, err := os.ReadDir(path)
if err != nil {
logrus.Errorln("Failed to read dir, err:", err)
return err
}
for _, file := range dir {
logrus.Println(file.Name())
os.Remove(path + file.Name())
}
return nil
}