Skip to content

Commit 059edd5

Browse files
committed
refactor(site): optimize image processing and error handling for site update
- Extract image resizing and base64 encoding logic into separate functions - Add error handling for image processing operations - Use default favicon base64 from repository instead of hardcoding - Improve logging and error messages in site service - Update user repository to use struct fields instead of query conditions
1 parent 5108859 commit 059edd5

File tree

5 files changed

+109
-82
lines changed

5 files changed

+109
-82
lines changed

internal/dal/repository/repository.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,10 @@ func autoMigrateAndInitialize(db *gorm.DB) {
123123
_, err = query.SysUser.WithContext(ctx).
124124
Where(
125125
query.SysUser.ID.Eq(1),
126-
query.SysUser.Username.Eq(DefaultUname),
127126
).
128127
Attrs(
129128
field.Attrs(&model.SysUser{
129+
Username: DefaultUname,
130130
Password: cryptor.Md5String(DefaultUPassword),
131131
}),
132132
).

internal/service/config/update.go

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,47 +6,20 @@
66
package config
77

88
import (
9-
"bytes"
10-
"encoding/base64"
11-
"mime/multipart"
12-
13-
"github.com/disintegration/imaging"
149
"github.com/gin-gonic/gin"
1510

1611
v1 "github.com/ch3nnn/webstack-go/api/v1"
1712
"github.com/ch3nnn/webstack-go/internal/dal/repository"
13+
"github.com/ch3nnn/webstack-go/pkg/tools"
1814
)
1915

2016
const (
2117
LogoWidth = 200
2218
LogoHeight = 50
23-
FaviconWidth = 32
24-
FaviconHeight = 32
19+
FaviconWidth = 64
20+
FaviconHeight = 64
2521
)
2622

27-
func resize2Image(f *multipart.FileHeader, width, height int) (base64Str string, err error) {
28-
file, err := f.Open()
29-
if err != nil {
30-
return
31-
}
32-
defer file.Close()
33-
34-
img, err := imaging.Decode(file, imaging.AutoOrientation(true))
35-
if err != nil {
36-
return
37-
}
38-
39-
var buf bytes.Buffer
40-
resize := imaging.Resize(img, width, height, imaging.Lanczos)
41-
if err = imaging.Encode(&buf, resize, imaging.PNG); err != nil {
42-
return
43-
}
44-
45-
base64Str = base64.StdEncoding.EncodeToString(buf.Bytes())
46-
47-
return
48-
}
49-
5023
func (s *service) Update(ctx *gin.Context, req *v1.ConfigUpdateReq) (resp *v1.ConfigUpdateResp, err error) {
5124
update := make(map[string]any)
5225
if req.SiteTitle != nil {
@@ -71,15 +44,15 @@ func (s *service) Update(ctx *gin.Context, req *v1.ConfigUpdateReq) (resp *v1.Co
7144
update["is_about"] = *req.IsAbout
7245
}
7346
if req.LogFile != nil {
74-
base64Str, err := resize2Image(req.LogFile, LogoWidth, LogoHeight)
47+
base64Str, err := tools.ResizeMultipartImgToBase64(req.LogFile, LogoWidth, LogoHeight)
7548
if err != nil {
7649
base64Str = repository.DefaultLogoBase64
7750
}
7851

7952
update["site_logo"] = base64Str
8053
}
8154
if req.FaviconFile != nil {
82-
base64Str, err := resize2Image(req.FaviconFile, FaviconWidth, FaviconHeight)
55+
base64Str, err := tools.ResizeMultipartImgToBase64(req.FaviconFile, FaviconWidth, FaviconHeight)
8356
if err != nil {
8457
base64Str = repository.DefaultFaviconBase64
8558
}

internal/service/site/service.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/gin-gonic/gin"
1717
"github.com/gocolly/colly"
1818
"github.com/mat/besticon/besticon"
19+
"github.com/pkg/errors"
1920

2021
v1 "github.com/ch3nnn/webstack-go/api/v1"
2122
"github.com/ch3nnn/webstack-go/internal/dal/repository"
@@ -61,9 +62,6 @@ func (s *service) i() {}
6162

6263
// -----------------------------------------------------------------------------------------------------------------------------------------
6364

64-
// default icon base64
65-
const defaultIcon = "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAA+VBMVEUAAAC6sWUzNjZCQkIsLi8sLjAsLi//tSs6Oj8tLzAsLi/9sycsLi/9sycsLi/9tCctLi/8tSj/tSguMTEuMzQzMzMwMzb/ujP9tCcsLi8uLzEtLy8sLi8sLi8tLi8sLi8tLi8sLi8tLjAsLi8sLy8sLi8sLjAsLjAtLy8tLzAtLzAuMDAuMDL/tyn9tCf8tCctLi/8tCf8tCf8tCf9sycsLjD9tCgsLjD9tSf9tCgtLzAtMDAuLzAvLzEvLzL/ty0tLy/+tij9tCj9tCj9syf9syj9tCf9tCj9tCf9tCn8tSj/tCj/tikwMDT/vzP/v0AsLy/8sycsLi+FeN01AAAAUXRSTlMAAg8F/uOqIwv7+Pjp6dLQdWM/KSIcFg3v7Uv18tzZzce5ta+ej4eBb2lUQT0x+8jBvrWvqpqLiollZGBcNjAck1T039fNo5h7cFpHOB8UCKLRW+BFAAACmElEQVRYw82VaVPyMBSFW5aC7FulgMiqICIIIiq4gPvum/7/H/NOe+00xwZL+OTzhZkm5wz35txE+eOo2ZExyqob63NpZpHObSaPTJjDJCIvL57HmUv8vChbfJIhyawqVzwg2YrICRNzEpEoHpBohXoBxXtIXqhSxUu0QlS8ZCuK0zhbj/i0KFu8fyuO0kyO9BHqDSaLAQ5jJs+YNzCYPAZvMGTyDHmDVybPq8KTjUvK41kFuZlI6Sc3gjl4WFv+kPO7hpD1L6fidOArH8AgeIiM/eITWSUtdIP279v9L/L7N3tPsFv4KY/ux8xwj1rxYqzK3gsV3wubsf0o6AN10+L4WrH4fBqIin/6tFevj+299QBv0DaJ0Ok2TefIox/R9G2fhkyizRuETYfSdyuWdyC/W34XXzIdwrzBrumyW7Y/fT3fMofb5y/7Wxn28QZnJk8zT+l+ZMQj5TbfhF1nvEFQg7WtPerQ+9Aa23fq894W7NGCCjBPwHJiplKwlhQcdfZjfa6IksBT63OL/RqsuSkACi0T0D4U4kPDhRaXQ+QwBRsrnYBVfKcCX1OHv72tByW0aC1aKC8dqCuniZq9wGYjW4uAuxfp10JtinG+sVLfyFOc2yGnxZiknQydba8qlFd7lJnMDuTIJuPsKbt7ANe97LhneIOU4F+CXFBfijdIeGN8Vef09StvnBO8gSY6qcuwM7iXojPWeAO9KspKtBOzctuJilJW1RVwEKdV7/7r6uKc6z4xhnmBSYM4Y4ydVkLl0A0iIYgzNBl7T+eBxyRCdGuFmrPyrBny3ndi4N4E4Mb1AWIsirMv9HYA+Or4Q68XQu+eBL0wqunllSEKN2GF4iyHrkFuN6FfwxdCHnXeKDXmqvKn+Q+oeE3vIQF62QAAAABJRU5ErkJggg=="
66-
6765
func getWebLogoIconBase64(url string) (string, error) {
6866
client := &http.Client{
6967
Timeout: 3 * time.Second,
@@ -77,12 +75,17 @@ func getWebLogoIconBase64(url string) (string, error) {
7775
besticon.WithLogger(besticon.NewDefaultLogger(io.Discard)), // disable verbose logging
7876
)
7977

80-
icons, err := b.NewIconFinder().FetchIcons(url)
81-
if err != nil || len(icons) == 0 {
82-
return defaultIcon, err
78+
finder := b.NewIconFinder()
79+
if _, err := finder.FetchIcons(url); err != nil {
80+
return repository.DefaultFaviconBase64, err
81+
}
82+
83+
icon := finder.IconInSizeRange(besticon.SizeRange{Min: 16, Perfect: 64, Max: 512})
84+
if icon == nil {
85+
return repository.DefaultFaviconBase64, errors.New("failed to fetch icons")
8386
}
8487

85-
return base64.StdEncoding.EncodeToString(icons[0].ImageData), nil
88+
return base64.StdEncoding.EncodeToString(icon.ImageData), nil
8689
}
8790

8891
func getWebTitle(url string) (title string, err error) {

internal/service/site/update.go

Lines changed: 18 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,51 +6,17 @@
66
package site
77

88
import (
9-
"crypto/tls"
10-
"encoding/base64"
11-
"io"
12-
"net/http"
13-
149
"github.com/gin-gonic/gin"
1510

1611
v1 "github.com/ch3nnn/webstack-go/api/v1"
12+
"github.com/ch3nnn/webstack-go/internal/dal/repository"
13+
"github.com/ch3nnn/webstack-go/pkg/tools"
1714
)
1815

19-
func getIconBase64ByFormFile(req *v1.SiteUpdateReq) string {
20-
file, err := req.File.Open()
21-
if err != nil {
22-
return defaultIcon
23-
}
24-
defer file.Close()
25-
26-
imgData, err := io.ReadAll(file)
27-
if err != nil {
28-
return defaultIcon
29-
}
30-
31-
return base64.StdEncoding.EncodeToString(imgData)
32-
}
33-
34-
func getIconBase64ByURL(req *v1.SiteUpdateReq) string {
35-
client := &http.Client{
36-
Transport: &http.Transport{
37-
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
38-
},
39-
}
40-
41-
resp, err := client.Get(req.Icon)
42-
if err != nil {
43-
return defaultIcon
44-
}
45-
defer resp.Body.Close()
46-
47-
imgData, err := io.ReadAll(resp.Body)
48-
if err != nil {
49-
return defaultIcon
50-
}
51-
52-
return base64.StdEncoding.EncodeToString(imgData)
53-
}
16+
const (
17+
FaviconWidth = 64
18+
FaviconHeight = 64
19+
)
5420

5521
func (s *service) Update(ctx *gin.Context, req *v1.SiteUpdateReq) (resp *v1.SiteUpdateResp, err error) {
5622
update := make(map[string]any)
@@ -62,10 +28,20 @@ func (s *service) Update(ctx *gin.Context, req *v1.SiteUpdateReq) (resp *v1.Site
6228
update["Title"] = req.Title
6329
}
6430
if req.Icon != "" {
65-
update["Icon"] = getIconBase64ByURL(req)
31+
base64Str, err := tools.ResizeURLImgToBase64(req.Icon, FaviconWidth, FaviconHeight)
32+
if err != nil {
33+
base64Str = repository.DefaultFaviconBase64
34+
}
35+
36+
update["Icon"] = base64Str
6637
}
6738
if req.File != nil {
68-
update["Icon"] = getIconBase64ByFormFile(req)
39+
base64Str, err := tools.ResizeMultipartImgToBase64(req.File, FaviconWidth, FaviconHeight)
40+
if err != nil {
41+
base64Str = repository.DefaultFaviconBase64
42+
}
43+
44+
update["Icon"] = base64Str
6945
}
7046
if req.Description != "" {
7147
update["Description"] = req.Description

pkg/tools/img.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* @Author: chentong
3+
* @Date: 2025/02/08 12:37
4+
*/
5+
6+
package tools
7+
8+
import (
9+
"bytes"
10+
"crypto/tls"
11+
"encoding/base64"
12+
"io"
13+
"mime/multipart"
14+
"net/http"
15+
16+
"github.com/disintegration/imaging"
17+
)
18+
19+
func resizeImg2Base64(r io.Reader, width, height int) (base64Str string, err error) {
20+
img, err := imaging.Decode(r, imaging.AutoOrientation(true))
21+
if err != nil {
22+
return
23+
}
24+
25+
var buf bytes.Buffer
26+
resize := imaging.Resize(img, width, height, imaging.Lanczos)
27+
if err = imaging.Encode(&buf, resize, imaging.PNG); err != nil {
28+
return
29+
}
30+
31+
base64Str = base64.StdEncoding.EncodeToString(buf.Bytes())
32+
33+
return
34+
}
35+
36+
// ResizeMultipartImgToBase64 将multipart.FileHeader表示的图片文件调整大小,并以base64编码字符串的形式返回。
37+
// 参数f是包含图片文件信息的multipart.FileHeader指针;
38+
// 参数width和height分别是目标图片的宽度和高度。
39+
// 返回值base64Str是调整大小后的图片的base64编码字符串;err是错误信息,如果执行过程中发生错误则不为nil。
40+
func ResizeMultipartImgToBase64(f *multipart.FileHeader, width, height int) (base64Str string, err error) {
41+
file, err := f.Open()
42+
if err != nil {
43+
return
44+
}
45+
defer file.Close()
46+
47+
return resizeImg2Base64(file, width, height)
48+
}
49+
50+
// ResizeURLImgToBase64 从指定的URL获取图像,并将其调整为指定的宽度和高度后,转换为Base64编码的字符串。
51+
// 参数:
52+
//
53+
// url - 图像的URL地址。
54+
// width - 调整后图像的宽度。
55+
// height - 调整后图像的高度。
56+
//
57+
// 返回值:
58+
//
59+
// base64Str - 转换后的Base64编码字符串。
60+
// err - 错误信息,如果执行过程中遇到任何错误,则返回该错误。
61+
func ResizeURLImgToBase64(url string, width, height int) (base64Str string, err error) {
62+
client := &http.Client{
63+
Transport: &http.Transport{
64+
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
65+
},
66+
}
67+
68+
resp, err := client.Get(url)
69+
if err != nil {
70+
return
71+
}
72+
defer resp.Body.Close()
73+
74+
return resizeImg2Base64(resp.Body, width, height)
75+
}

0 commit comments

Comments
 (0)