Files
RenewCMS/internal/infrastructure/useCases/BackfillImageMetadata.go
T

91 lines
2.0 KiB
Go

package useCases
import (
"RenewCMS/internal/domain/image"
"bytes"
"crypto/sha256"
"encoding/hex"
stdimage "image"
"io"
"path"
_ "golang.org/x/image/webp"
_ "image/jpeg"
_ "image/png"
)
var extensionContentTypes = map[string]string{
".png": "image/png",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".webp": "image/webp",
".svg": "image/svg+xml",
}
type BackfillImageMetadataUseCase struct {
imageRepository image.Repository
storage image.Storage
}
func NewBackfillImageMetadataUseCase(imageRepository image.Repository, storage image.Storage) *BackfillImageMetadataUseCase {
return &BackfillImageMetadataUseCase{imageRepository, storage}
}
func (u *BackfillImageMetadataUseCase) Run() error {
pending, err := u.imageRepository.ListMissingMetadata()
if err != nil {
return err
}
for _, row := range pending {
metadata, ok := u.readStoredImage(row.Path)
if !ok {
continue
}
if err := u.imageRepository.UpdateMetadata(row.ID, metadata); err != nil {
return err
}
}
return nil
}
func (u *BackfillImageMetadataUseCase) readStoredImage(storedPath string) (image.Metadata, bool) {
fileName := image.StoredName(storedPath)
contentType, known := extensionContentTypes[path.Ext(fileName)]
if !known {
return image.Metadata{}, false
}
data, err := u.read(fileName)
if err != nil {
return image.Metadata{}, false
}
width, height := 0, 0
if contentType != "image/svg+xml" {
config, _, err := stdimage.DecodeConfig(bytes.NewReader(data))
if err != nil {
return image.Metadata{}, false
}
width, height = config.Width, config.Height
}
checksum := sha256.Sum256(data)
return image.Metadata{
Filename: fileName,
Size: int64(len(data)),
ContentType: contentType,
Width: width,
Height: height,
SHA256: hex.EncodeToString(checksum[:]),
}, true
}
func (u *BackfillImageMetadataUseCase) read(storedName string) ([]byte, error) {
blob, err := u.storage.Open(storedName)
if err != nil {
return nil, err
}
defer blob.Content.Close()
return io.ReadAll(blob.Content)
}