diff --git a/worker/internal/services/image.go b/worker/internal/services/image.go new file mode 100644 index 0000000..317e4d7 --- /dev/null +++ b/worker/internal/services/image.go @@ -0,0 +1,34 @@ +package services + +import ( + "errors" + "os/exec" + "worker/internal/utils" +) + +func CompressImage(filePath string, mimeType string) (string, error) { + compressedPath := filePath + "_compressed" + switch mimeType { + case "image/png": + args := []string{"--output", compressedPath, filePath} + cmd := exec.Command("pngquant", args...) + _, err := cmd.CombinedOutput() + if err != nil { + return "", err + } + case "image/jpeg": + err := utils.CopyFile(filePath, compressedPath) + if err != nil { + return "", err + } + args := []string{"-m", "90", "--strip-all", compressedPath} + cmd := exec.Command("jpegoptim", args...) + _, err = cmd.CombinedOutput() + if err != nil { + return "", err + } + default: + return "", errors.New("不支持的文件类型") + } + return compressedPath, nil +} diff --git a/worker/internal/tasks/file.go b/worker/internal/tasks/file.go index 2fe5498..f71348a 100644 --- a/worker/internal/tasks/file.go +++ b/worker/internal/tasks/file.go @@ -12,12 +12,7 @@ import ( "github.com/hibiken/asynq" ) -type RemoveFileTaskPayload struct { - FileId string `json:"file_id"` -} - func RemoveFile(ctx context.Context, task *asynq.Task) error { - var payload RemoveFileTaskPayload if err := json.Unmarshal(task.Payload(), &payload); err != nil { return err diff --git a/worker/internal/tasks/image.go b/worker/internal/tasks/image.go index 123ee07..579ee4d 100644 --- a/worker/internal/tasks/image.go +++ b/worker/internal/tasks/image.go @@ -4,8 +4,6 @@ import ( "context" "encoding/json" "errors" - "fmt" - "os/exec" "path/filepath" "pkg/models" "worker/internal/services" @@ -14,14 +12,6 @@ import ( "github.com/hibiken/asynq" ) -type ImageTaskPayload struct { - FileId string `json:"file_id"` -} - -type CompressImageTaskPayload struct { - ImageTaskPayload -} - func CompressImage(ctx context.Context, task *asynq.Task) error { var payload CompressImageTaskPayload if err := json.Unmarshal(task.Payload(), &payload); err != nil { @@ -36,29 +26,10 @@ func CompressImage(ctx context.Context, task *asynq.Task) error { return err } originalPath := filepath.Join(uploadPath, payload.FileId) - switch originalFileInfo.MimeType { - case "image/png": - args := []string{"--output", originalPath + "_compressed", originalPath} - cmd := exec.Command("pngquant", args...) - _, err := cmd.CombinedOutput() - if err != nil { - return err - } - case "image/jpeg": - err := utils.CopyFile(originalPath, originalPath+"_compressed") - if err != nil { - return err - } - args := []string{"-m", "90", "--strip-all", originalPath + "_compressed"} - cmd := exec.Command("jpegoptim", args...) - _, err = cmd.CombinedOutput() - if err != nil { - return err - } - default: - return errors.New("不支持的文件类型") + compressedPath, err := services.CompressImage(originalPath, originalFileInfo.MimeType) + if err != nil { + return err } - compressedPath := fmt.Sprintf("%s_compressed", originalPath) compressedFileInfo, err := services.GenStandardFile(compressedPath, originalFileInfo.MimeType) if err != nil { return err diff --git a/worker/internal/tasks/types.go b/worker/internal/tasks/types.go new file mode 100644 index 0000000..13f1e21 --- /dev/null +++ b/worker/internal/tasks/types.go @@ -0,0 +1,13 @@ +package tasks + +type BaseFileTaskPayload struct { + FileId string `json:"file_id"` +} + +type RemoveFileTaskPayload struct { + BaseFileTaskPayload +} + +type CompressImageTaskPayload struct { + BaseFileTaskPayload +} diff --git a/worker/test/resource/test.jpg b/worker/test/resource/test.jpg new file mode 100644 index 0000000..8c156be Binary files /dev/null and b/worker/test/resource/test.jpg differ diff --git a/worker/test/resource/test.png b/worker/test/resource/test.png new file mode 100644 index 0000000..e73afc7 Binary files /dev/null and b/worker/test/resource/test.png differ diff --git a/worker/test/resource/test.svg b/worker/test/resource/test.svg new file mode 100644 index 0000000..f76d8ee --- /dev/null +++ b/worker/test/resource/test.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/worker/test/services/image_test.go b/worker/test/services/image_test.go new file mode 100644 index 0000000..c402d46 --- /dev/null +++ b/worker/test/services/image_test.go @@ -0,0 +1,66 @@ +package services + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "testing" + "worker/internal/services" + "worker/internal/utils" + + "github.com/stretchr/testify/assert" +) + +func TestCompressPNGHappyPath(t *testing.T) { + tmp := t.TempDir() + filePath := filepath.Join(tmp, "test.png") + // 从 test/resource 复制真实 PNG,路径基于当前测试文件位置 + _, self, _, _ := runtime.Caller(0) + srcPath := filepath.Join(filepath.Dir(self), "..", "resource", "test.png") + err := utils.CopyFile(srcPath, filePath) + if err != nil { + t.Fatal(err) + } + got, err := services.CompressImage(filePath, "image/png") + if err != nil { + t.Fatal(err) + } + assert.Equal(t, got, filePath+"_compressed") + origInfo, err := os.Stat(filePath) + if err != nil { + t.Fatal(err) + } + compInfo, err := os.Stat(got) + if err != nil { + t.Fatal(err) + } + assert.NotEqual(t, origInfo.Size(), compInfo.Size()) + fmt.Printf("原图: %d | 压缩后: %d | 压缩率: %f%%\n", origInfo.Size(), compInfo.Size(), float64(origInfo.Size())/float64(compInfo.Size())*100) +} + +func TestCompressJPEGHappyPath(t *testing.T) { + tmp := t.TempDir() + filePath := filepath.Join(tmp, "test.jpg") + _, self, _, _ := runtime.Caller(0) + srcPath := filepath.Join(filepath.Dir(self), "..", "resource", "test.jpg") + err := utils.CopyFile(srcPath, filePath) + if err != nil { + t.Fatal(err) + } + got, err := services.CompressImage(filePath, "image/jpeg") + if err != nil { + t.Fatal(err) + } + assert.Equal(t, got, filePath+"_compressed") + origInfo, err := os.Stat(filePath) + if err != nil { + t.Fatal(err) + } + compInfo, err := os.Stat(got) + if err != nil { + t.Fatal(err) + } + assert.NotEqual(t, origInfo.Size(), compInfo.Size()) + fmt.Printf("原图: %d | 压缩后: %d | 压缩率: %f%%\n", origInfo.Size(), compInfo.Size(), float64(origInfo.Size())/float64(compInfo.Size())*100) +}