feat(utils): add file utility functions for MD5 hashing, file ID generation, and upload directory management

This commit is contained in:
keven1024
2026-02-27 12:08:13 +08:00
parent 22637bcf6e
commit ed7ac4e657
5 changed files with 97 additions and 13 deletions

70
pkg/utils/file.go Normal file
View File

@@ -0,0 +1,70 @@
package utils
import (
"bufio"
"crypto/md5"
"fmt"
"io"
"os"
"path/filepath"
"github.com/dustin/go-humanize"
)
func GetFileId(fileHash string, fileSize int64) string {
return fmt.Sprintf("%s_%d", fileHash, fileSize)
}
func GetFileMd5(file io.Reader) (string, error) {
const bufferSize = 1024 * 1000 // 1MB
hash := md5.New()
buf := make([]byte, bufferSize)
reader := bufio.NewReader(file)
for {
n, err := reader.Read(buf)
if err != nil {
if err == io.EOF {
break
}
return "", err
}
hash.Write(buf[:n])
}
return fmt.Sprintf("%x", hash.Sum(nil)), nil
}
func GetUploadDirPath() (string, error) {
uploadPath := GetEnv("upload.path")
if uploadPath == "" {
basepath, err := os.Getwd()
if err != nil {
return "", err
}
uploadPath = filepath.Join(basepath, "uploads")
}
if err := os.MkdirAll(uploadPath, 0755); err != nil {
return "", err
}
return uploadPath, nil
}
func GetFileSize(size string) (uint64, error) {
return humanize.ParseBytes(size)
}
func CopyFile(src, dst string) error {
sourceFile, err := os.Open(src)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(dst)
if err != nil {
return err
}
defer destFile.Close()
_, err = io.Copy(destFile, sourceFile)
return err
}

View File

@@ -3,6 +3,7 @@ module pkg/utils
go 1.25.5
require (
github.com/dustin/go-humanize v1.0.1
github.com/hibiken/asynq v0.25.1
github.com/redis/go-redis/v9 v9.17.3
github.com/spf13/viper v1.21.0

View File

@@ -6,6 +6,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=

View File

@@ -19,37 +19,37 @@ func GenStandardFile(filePath string, mimeType string) (GenStandardFileReturn, e
if _, err := os.Stat(filePath); os.IsNotExist(err) {
return GenStandardFileReturn{}, errors.New("文件不存在")
}
compressedFile, err := os.Open(filePath)
file, err := os.Open(filePath)
if err != nil {
return GenStandardFileReturn{}, err
}
defer compressedFile.Close()
defer file.Close()
compressedFileInfo, err := compressedFile.Stat()
fileInfo, err := file.Stat()
if err != nil {
return GenStandardFileReturn{}, err
}
compressedFileSize := compressedFileInfo.Size()
fileSize := fileInfo.Size()
compressedFileHash, err := utils.GetFileMd5(compressedFile)
fileHash, err := utils.GetFileMd5(file)
if err != nil {
return GenStandardFileReturn{}, err
}
compressedFileId := utils.GetFileId(compressedFileHash, compressedFileSize)
fileId := utils.GetFileId(fileHash, fileSize)
uploadPath, err := utils.GetUploadDirPath()
if err != nil {
return GenStandardFileReturn{}, err
}
newPath := filepath.Join(uploadPath, compressedFileId)
newPath := filepath.Join(uploadPath, fileId)
if err := os.Rename(filePath, newPath); err != nil {
return GenStandardFileReturn{}, err
}
models.SetRedisFileInfo(compressedFileId, models.RedisFileInfo{
models.SetRedisFileInfo(fileId, models.RedisFileInfo{
FileInfo: models.FileInfo{
FileSize: compressedFileSize,
FileHash: compressedFileHash,
FileSize: fileSize,
FileHash: fileHash,
MimeType: mimeType,
},
FileType: models.FileTypeUpload,
@@ -57,10 +57,10 @@ func GenStandardFile(filePath string, mimeType string) (GenStandardFileReturn, e
})
return GenStandardFileReturn{
FileId: compressedFileId,
FileId: fileId,
FileInfo: models.FileInfo{
FileSize: compressedFileSize,
FileHash: compressedFileHash,
FileSize: fileSize,
FileHash: fileHash,
MimeType: mimeType,
},
}, nil

View File

@@ -1,5 +1,12 @@
package tasks
import "errors"
var (
ErrNotFoundFile = errors.New("NotFoundFile")
ErrUnknown = errors.New("Unknown")
)
type BaseFileTaskPayload struct {
FileId string `json:"file_id"`
}
@@ -11,3 +18,8 @@ type RemoveFileTaskPayload struct {
type CompressImageTaskPayload struct {
BaseFileTaskPayload
}
type ConvertImageTaskPayload struct {
BaseFileTaskPayload
TargetExt string `json:"target_ext"`
}