minio-worker-go/processor.go

115 lines
3.3 KiB
Go

package main
import (
"bytes"
"context"
"fmt"
"log"
"path"
"path/filepath"
"strings"
"github.com/h2non/bimg"
"github.com/minio/minio-go/v7"
)
func ProcessImage(ctx context.Context, client *minio.Client, bucket, key string) error {
stat, err := client.StatObject(ctx, bucket, key, minio.StatObjectOptions{})
if err != nil {
log.Printf("🚨 Failed to stat object: %s, error: %v", key, err)
return err
}
if !strings.HasPrefix(stat.ContentType, "image/") {
log.Printf("⏭️ Skipping non-image file: %s", key)
return nil
}
if stat.UserMetadata["Processed"] == "true" || stat.UserMetadata["X-Amz-Meta-Processed"] == "true" {
log.Printf("⏭️ Skipping already processed image: %s", key)
return nil
}
object, err := client.GetObject(ctx, bucket, key, minio.GetObjectOptions{})
if err != nil {
log.Printf("🚨 Failed to get object: %s, error: %v", key, err)
return err
}
defer object.Close()
sourceBuffer := new(bytes.Buffer)
if _, err := sourceBuffer.ReadFrom(object); err != nil {
log.Printf("🚨 Failed to read object: %s, error: %v", key, err)
return err
}
img := bimg.NewImage(sourceBuffer.Bytes())
fileName := filepath.Base(key)
filePath := path.Dir(key)
meta := map[string]string{
"Processed": "true",
}
if err := generateAndUploadJPEG(ctx, client, img, bucket, filePath, fileName, meta); err != nil {
return err
}
if err := generateAndUploadWebP(ctx, client, img, bucket, filePath, fileName, meta); err != nil {
return err
}
if err := generateAndUploadThumbnail(ctx, client, img, bucket, filePath, fileName, meta); err != nil {
return err
}
if err := UploadToMinIO(ctx, client, bucket, key, stat.ContentType, sourceBuffer.Bytes(), meta); err != nil {
return fmt.Errorf("failed to reupload original image: %w", err)
}
log.Printf("✅ Image processed: %s", key)
return nil
}
func generateAndUploadJPEG(ctx context.Context, client *minio.Client, img *bimg.Image, bucket, filePath, fileName string, meta map[string]string) error {
jpegBuf, err := img.Process(bimg.Options{
Quality: 90,
Type: bimg.JPEG,
StripMetadata: true,
})
if err != nil {
return fmt.Errorf("failed to generate optimized JPEG: %w", err)
}
return UploadToMinIO(ctx, client, bucket, path.Join(filePath, "optimized", fileName), "image/jpeg", jpegBuf, meta)
}
func generateAndUploadWebP(ctx context.Context, client *minio.Client, img *bimg.Image, bucket, filePath, fileName string, meta map[string]string) error {
webpBuf, err := img.Process(bimg.Options{
Quality: 90,
Type: bimg.WEBP,
StripMetadata: true,
})
if err != nil {
return fmt.Errorf("failed to generate WebP: %w", err)
}
webpName := strings.TrimSuffix(fileName, filepath.Ext(fileName)) + ".webp"
return UploadToMinIO(ctx, client, bucket, path.Join(filePath, "webp", webpName), "image/webp", webpBuf, meta)
}
func generateAndUploadThumbnail(ctx context.Context, client *minio.Client, img *bimg.Image, bucket, filePath, fileName string, meta map[string]string) error {
thumbBuf, err := img.Process(bimg.Options{
Width: 400,
Quality: 85,
Type: bimg.JPEG,
StripMetadata: true,
})
if err != nil {
return fmt.Errorf("failed to generate thumbnail: %w", err)
}
return UploadToMinIO(ctx, client, bucket, path.Join(filePath, "thumbs", fileName), "image/jpeg", thumbBuf, meta)
}