198 lines
5.9 KiB
Go
198 lines
5.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"runtime"
|
|
"strings"
|
|
"time"
|
|
|
|
"regexp"
|
|
"strconv"
|
|
|
|
"encoding/json"
|
|
|
|
"git.satori.love/gameui/webp/models"
|
|
_ "github.com/go-sql-driver/mysql"
|
|
)
|
|
|
|
//func init() {
|
|
// log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
|
|
//}
|
|
|
|
// string 转换为 int, 如果转换失败则返回默认值
|
|
func stringToInt(str string, defaultValue int) int {
|
|
if str == "" {
|
|
return defaultValue
|
|
}
|
|
value, err := strconv.Atoi(str)
|
|
if err != nil {
|
|
return defaultValue
|
|
}
|
|
return value
|
|
}
|
|
|
|
func LogComponent(startTime int64, r *http.Request) {
|
|
endTime := fmt.Sprintf("%dms", (time.Now().UnixNano()-startTime)/1000000)
|
|
log.Println(r.Method, r.URL.Path, endTime)
|
|
}
|
|
|
|
type Image struct {
|
|
Id int `json:"id"`
|
|
Content string `json:"content"`
|
|
CreateTime time.Time `json:"create_time"`
|
|
UpdateTime time.Time `json:"update_time"`
|
|
}
|
|
|
|
type Images struct {
|
|
Page int `json:"page"`
|
|
PageSize int `json:"page_size"`
|
|
Total int `json:"total"`
|
|
List []Image `json:"list"`
|
|
}
|
|
|
|
func main() {
|
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
|
|
|
var mysqlConnection models.MysqlConnection
|
|
mysqlConnection.Init()
|
|
|
|
// 获取图片信息列表(分页)
|
|
http.HandleFunc("/images", func(w http.ResponseWriter, r *http.Request) {
|
|
defer LogComponent(time.Now().UnixNano(), r) // 最后打印日志
|
|
|
|
// 私域: (自己的图片, 自己的文章, 自己的精选集, 点赞收藏精选集)
|
|
// 条件查询(模糊搜索, 时间区间, 作者, 标签, 分类, 精选集, 状态, 置顶, 模糊权重)(权重规则:权重指数)
|
|
// 条件筛选(交集, 并集, 差集, 子集)
|
|
// 排序
|
|
// 分页
|
|
|
|
// 按标签查询
|
|
var tags string
|
|
if list := strings.Split(r.URL.Query().Get("tags"), ","); len(list) > 0 {
|
|
for _, tag := range list {
|
|
tags += fmt.Sprintf("'%s',", tag)
|
|
}
|
|
tags = tags[:len(tags)-1]
|
|
fmt.Println(tags)
|
|
}
|
|
|
|
// 按分类查询
|
|
var categories string
|
|
if list := strings.Split(r.URL.Query().Get("categories"), ","); len(list) > 0 {
|
|
for _, category := range list {
|
|
categories += fmt.Sprintf("'%s',", category)
|
|
}
|
|
categories = categories[:len(categories)-1]
|
|
fmt.Println(categories)
|
|
}
|
|
|
|
// 获取图片列表
|
|
var images Images
|
|
images.Page, images.PageSize = stringToInt(r.URL.Query().Get("page"), 1), stringToInt(r.URL.Query().Get("pageSize"), 10)
|
|
rows, err := mysqlConnection.Database.Query("SELECT id, content, update_time, create_time FROM web_images LIMIT ?, ?", (images.Page-1)*images.PageSize, images.PageSize)
|
|
if err != nil {
|
|
log.Println("获取图片列表失败", err)
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// 处理结果集
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
var image Image
|
|
rows.Scan(&image.Id, &image.Content, &image.UpdateTime, &image.CreateTime)
|
|
image.UpdateTime = image.UpdateTime.UTC()
|
|
image.CreateTime = image.CreateTime.UTC()
|
|
image.Content = regexp.MustCompile(`http:`).ReplaceAllString(image.Content, "https:")
|
|
images.List = append(images.List, image)
|
|
}
|
|
|
|
// 获取总数
|
|
err = mysqlConnection.Database.QueryRow("SELECT COUNT(*) FROM web_images").Scan(&images.Total)
|
|
if err != nil {
|
|
log.Println("获取图片总数失败", err)
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// 将对象转换为有缩进的JSON输出
|
|
data, err := json.MarshalIndent(images, "", " ")
|
|
if err != nil {
|
|
log.Println("转换图片列表失败", err)
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
|
w.Write(data)
|
|
|
|
})
|
|
|
|
// URL 格式: /img/{type}-{id}.{format}?width=320&height=320&fit=cover
|
|
http.HandleFunc("/img/", func(w http.ResponseWriter, r *http.Request) {
|
|
defer LogComponent(time.Now().UnixNano(), r) // 最后打印日志
|
|
|
|
reg := regexp.MustCompile(`^/img/([0-9a-zA-Z]+)-([0-9a-zA-Z]+).(jpg|jpeg|png|webp)$`)
|
|
matches := reg.FindStringSubmatch(r.URL.Path)
|
|
if len(matches) != 4 {
|
|
http.Error(w, "URL 格式错误", http.StatusNotFound)
|
|
return
|
|
}
|
|
group, id, format, width, height, fit := matches[1], matches[2], matches[3], stringToInt(r.URL.Query().Get("width"), 0), stringToInt(r.URL.Query().Get("height"), 0), r.URL.Query().Get("fit")
|
|
content, err := mysqlConnection.GetImageContent(group, id)
|
|
if err != nil {
|
|
log.Println("获取图片失败", format, err)
|
|
http.Error(w, err.Error(), http.StatusNotFound)
|
|
return
|
|
}
|
|
var img models.Image
|
|
img.Init(content)
|
|
data, err := img.ToWebP(width, height, fit)
|
|
if err != nil {
|
|
log.Println("转换图片失败", err)
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "image/webp")
|
|
w.Header().Set("Cache-Control", "max-age=31536000")
|
|
w.Write(data)
|
|
})
|
|
|
|
// URL 格式: /webp/{type}-{id}-{version}-{width}-{height}-{fit}.{format}
|
|
http.HandleFunc("/webp/", func(w http.ResponseWriter, r *http.Request) {
|
|
defer LogComponent(time.Now().UnixNano(), r) // 最后打印日志
|
|
|
|
reg := regexp.MustCompile(`^/webp/([0-9a-zA-Z]+)-([0-9a-zA-Z]+)-([0-9a-zA-Z]+)-([0-9]+)-([0-9]+)-([a-zA-Z]+).(jpg|jpeg|png|webp)$`)
|
|
matches := reg.FindStringSubmatch(r.URL.Path)
|
|
if len(matches) != 8 {
|
|
log.Println("URL 格式错误", matches)
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
group, id, version, width, height, fit, format := matches[1], matches[2], matches[3], stringToInt(matches[4], 0), stringToInt(matches[5], 0), matches[6], matches[7]
|
|
content, err := mysqlConnection.GetImageContent(group, id)
|
|
if err != nil {
|
|
log.Println("获取图片失败", version, format, err)
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
var img models.Image
|
|
img.Init(content)
|
|
data, err := img.ToWebP(width, height, fit)
|
|
if err != nil {
|
|
log.Println("转换图片失败", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "image/webp")
|
|
w.Header().Set("Cache-Control", "max-age=31536000")
|
|
w.Write(data)
|
|
})
|
|
|
|
log.Println("Server is running at http://localhost:6001")
|
|
http.ListenAndServe(":6001", nil)
|
|
}
|