相似推荐合并接口
This commit is contained in:
458
bin/main.go
458
bin/main.go
@@ -39,6 +39,8 @@ func LogComponent(startTime int64, r *http.Request) {
|
|||||||
|
|
||||||
type Image struct {
|
type Image struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
|
Width int `json:"width"`
|
||||||
|
Height int `json:"height"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
CreateTime time.Time `json:"create_time"`
|
CreateTime time.Time `json:"create_time"`
|
||||||
UpdateTime time.Time `json:"update_time"`
|
UpdateTime time.Time `json:"update_time"`
|
||||||
@@ -59,13 +61,50 @@ type ListView struct {
|
|||||||
List []interface{} `json:"list"`
|
List []interface{} `json:"list"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var mysqlConnection models.MysqlConnection
|
||||||
|
var milvusConnection models.MilvusConnection
|
||||||
|
|
||||||
|
func (image *Image) GetSimilarImagesIdList(collection_name string) (ids []int64) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
// 先从milvus中查询图片的向量
|
||||||
|
result, err := milvusConnection.Client.Query(ctx, collection_name, nil, fmt.Sprintf("id in [%d]", image.Id), []string{"embedding"})
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Milvus query failed:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var embedding []float32
|
||||||
|
for _, item := range result {
|
||||||
|
if item.Name() == "embedding" {
|
||||||
|
embedding = item.FieldData().GetVectors().GetFloatVector().Data
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: 处理向量不存在的情况(生成)
|
||||||
|
// TODO: 处理图片不存在的情况(404)
|
||||||
|
|
||||||
|
// 用向量查询相似图片
|
||||||
|
sp, _ := entity.NewIndexIvfFlatSearchParam(64)
|
||||||
|
vectors := []entity.Vector{entity.FloatVector(embedding)}
|
||||||
|
resultx, err := milvusConnection.Client.Search(ctx, collection_name, nil, "", []string{"id", "article_id"}, vectors, "embedding", entity.L2, 10, sp)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Milvus search failed:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输出结果
|
||||||
|
for _, item := range resultx {
|
||||||
|
//fmt.Println(item.Scores)
|
||||||
|
//fmt.Println(item.IDs.FieldData().GetScalars().GetLongData().GetData())
|
||||||
|
ids = item.IDs.FieldData().GetScalars().GetLongData().GetData()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
|
|
||||||
var mysqlConnection models.MysqlConnection
|
|
||||||
mysqlConnection.Init()
|
mysqlConnection.Init()
|
||||||
|
|
||||||
var milvusConnection models.MilvusConnection
|
|
||||||
milvusConnection.Init()
|
milvusConnection.Init()
|
||||||
err := milvusConnection.Client.LoadCollection(context.Background(), "default", false)
|
err := milvusConnection.Client.LoadCollection(context.Background(), "default", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -73,6 +112,238 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取图片信息列表(分页)
|
||||||
|
http.HandleFunc("/images", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
defer LogComponent(time.Now().UnixNano(), r) // 最后打印日志
|
||||||
|
|
||||||
|
// 私域: (自己的图片, 自己的文章, 自己的精选集, 点赞收藏精选集)
|
||||||
|
// 条件查询(模糊搜索, 时间区间, 作者, 标签, 分类, 精选集, 状态, 置顶, 模糊权重)(权重规则:权重指数)
|
||||||
|
// 条件筛选(交集, 并集, 差集, 子集)
|
||||||
|
// 排序
|
||||||
|
// 分页
|
||||||
|
|
||||||
|
// 获取查询条件(忽略空值), 超级简洁写法
|
||||||
|
QueryConditions := func(key string) (list []string) {
|
||||||
|
for _, item := range strings.Split(r.URL.Query().Get(key), ",") {
|
||||||
|
if item != "" {
|
||||||
|
list = append(list, fmt.Sprintf("'%s'", item))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拼接查询条件, 超级简洁写法
|
||||||
|
conditions := ""
|
||||||
|
if authors := QueryConditions("authors"); len(authors) > 0 {
|
||||||
|
conditions += fmt.Sprintf(" AND author IN (%s)", strings.Join(authors, ","))
|
||||||
|
}
|
||||||
|
if tags := QueryConditions("tags"); len(tags) > 0 {
|
||||||
|
conditions += fmt.Sprintf(" AND tag IN (%s)", strings.Join(tags, ","))
|
||||||
|
}
|
||||||
|
if categories := QueryConditions("categories"); len(categories) > 0 {
|
||||||
|
conditions += fmt.Sprintf(" AND categorie IN (%s)", strings.Join(categories, ","))
|
||||||
|
}
|
||||||
|
if sets := QueryConditions("sets"); len(sets) > 0 {
|
||||||
|
conditions += fmt.Sprintf(" AND sets IN (%s)", strings.Join(sets, ","))
|
||||||
|
}
|
||||||
|
var ids []int64
|
||||||
|
if similar := QueryConditions("similar"); len(similar) > 0 {
|
||||||
|
// 避免报错: strconv.Atoi failed: strconv.Atoi: parsing "'8888'": invalid syntax
|
||||||
|
id, err := strconv.Atoi(strings.Trim(similar[0], "'"))
|
||||||
|
if err != nil {
|
||||||
|
log.Println("strconv.Atoi failed:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("id:", id)
|
||||||
|
|
||||||
|
// 如果指定以某个图片为基准的相似图片列表范围, 获取相似图片ID的列表
|
||||||
|
ids = (&Image{Id: id}).GetSimilarImagesIdList("default")
|
||||||
|
fmt.Println("ids:", ids)
|
||||||
|
idsStr := make([]string, len(ids))
|
||||||
|
for i, v := range ids {
|
||||||
|
idsStr[i] = strconv.FormatInt(v, 10)
|
||||||
|
}
|
||||||
|
if len(idsStr) > 0 {
|
||||||
|
conditions += fmt.Sprintf(" AND id IN (%s)", strings.Join(idsStr, ",")) // 拼接查询条件
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if conditions != "" {
|
||||||
|
conditions = strings.Replace(conditions, " AND", "", 1) // 去掉第一个 AND
|
||||||
|
conditions = " WHERE" + conditions // 拼接 WHERE
|
||||||
|
fmt.Println(conditions) // 打印查询条件
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印查询语句
|
||||||
|
fmt.Println("SELECT id, width, height, content, update_time, create_time FROM web_images" + conditions + " LIMIT ?, ?")
|
||||||
|
|
||||||
|
// 获取图片列表
|
||||||
|
var images ListView
|
||||||
|
var image_list []Image
|
||||||
|
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, width, height, content, update_time, create_time FROM web_images"+conditions+" 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.Width, &image.Height, &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:")
|
||||||
|
image_list = append(image_list, image)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果使用了相似图片列表范围, 需要按照相似图片ID原本的顺序重新排序, 需要注意的是, 相似图片ID列表中可能会包含不在当前页的图片ID
|
||||||
|
if similar := QueryConditions("similar"); len(similar) > 0 {
|
||||||
|
// 用于存储排序后的图片列表
|
||||||
|
var image_list_sorted []Image
|
||||||
|
for _, id := range ids {
|
||||||
|
for _, image := range image_list {
|
||||||
|
if image.Id == int(id) {
|
||||||
|
image_list_sorted = append(image_list_sorted, image)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
image_list = image_list_sorted
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将 []Image 转换为 []interface{}
|
||||||
|
images.List = make([]interface{}, len(image_list))
|
||||||
|
for i, v := range image_list {
|
||||||
|
images.List[i] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取总数
|
||||||
|
err = mysqlConnection.Database.QueryRow("SELECT COUNT(*) FROM web_images" + conditions).Scan(&images.Total)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("获取图片总数失败", err)
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否有下一页
|
||||||
|
images.Next = images.Total > images.Page*images.PageSize
|
||||||
|
|
||||||
|
// 将对象转换为有缩进的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)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取相似图片列表
|
||||||
|
http.HandleFunc("/similar", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
defer LogComponent(time.Now().UnixNano(), r) // 最后打印日志
|
||||||
|
|
||||||
|
var collection_name = "default" // 图片集合名称
|
||||||
|
var image Image = Image{Id: 8888} // 图片对象
|
||||||
|
|
||||||
|
ids := image.GetSimilarImagesIdList(collection_name)
|
||||||
|
|
||||||
|
var listview ListView
|
||||||
|
|
||||||
|
// 是否有下一页
|
||||||
|
listview.Total = 10
|
||||||
|
listview.Next = false
|
||||||
|
listview.Page = 1
|
||||||
|
listview.PageSize = 10
|
||||||
|
|
||||||
|
// 获取一组ID对应的图片数据
|
||||||
|
ids_str := strings.Trim(strings.Replace(fmt.Sprint(ids), " ", ",", -1), "[]")
|
||||||
|
println(ids_str)
|
||||||
|
rows, err := mysqlConnection.Database.Query("SELECT id, content, update_time, create_time, width, height FROM web_images WHERE id in (" + ids_str + ")")
|
||||||
|
if err != nil {
|
||||||
|
log.Println("SQL查询失败:", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for rows.Next() {
|
||||||
|
var image Image
|
||||||
|
err := rows.Scan(&image.Id, &image.Content, &image.UpdateTime, &image.CreateTime, &image.Width, &image.Height)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("SQL查询失败:", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
listview.List = append(listview.List, image)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将对象转换为有缩进的JSON输出
|
||||||
|
json, err := json.MarshalIndent(listview, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输出JSON
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.Write(json)
|
||||||
|
|
||||||
|
//result, err := milvusConnection.Client.Query(
|
||||||
|
// context.Background(), // ctx
|
||||||
|
// collection_name, // CollectionName
|
||||||
|
// nil, // PartitionName
|
||||||
|
// fmt.Sprintf("id in [%s]", id), // expr
|
||||||
|
// []string{"id", "embedding", "article_id"}, // OutputFields
|
||||||
|
//)
|
||||||
|
//if err != nil {
|
||||||
|
// log.Println(err)
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
//// TODO: 不存在则重建向量
|
||||||
|
//var similar Similar
|
||||||
|
//for _, item := range result {
|
||||||
|
// if item.Name() == "id" {
|
||||||
|
// similar.Id = item.FieldData().GetScalars().GetLongData().GetData()[0]
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// if item.Name() == "article_id" {
|
||||||
|
// similar.ArticleId = item.FieldData().GetScalars().GetLongData().GetData()[0]
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// if item.Name() == "embedding" {
|
||||||
|
// similar.Embedding = item.FieldData().GetVectors().GetFloatVector().Data
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//// 用向量查询相似图片
|
||||||
|
//sp, _ := entity.NewIndexIvfFlatSearchParam(64)
|
||||||
|
//vectors := []entity.Vector{
|
||||||
|
// entity.FloatVector(similar.Embedding),
|
||||||
|
//}
|
||||||
|
//resultx, err := milvusConnection.Client.Search(
|
||||||
|
// context.Background(), // ctx
|
||||||
|
// collection_name, // CollectionName
|
||||||
|
// nil, // PartitionNames
|
||||||
|
// "", // expr
|
||||||
|
// []string{"id", "article_id"}, // OutputFields
|
||||||
|
// vectors, // vectors
|
||||||
|
// "embedding", // vectorField
|
||||||
|
// entity.L2, // entity.MetricType
|
||||||
|
// 10, // topK
|
||||||
|
// sp, // searchParam
|
||||||
|
//)
|
||||||
|
//if err != nil {
|
||||||
|
// log.Println(err)
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
//// 输出结果
|
||||||
|
//for _, item := range resultx {
|
||||||
|
// fmt.Println(item.Scores)
|
||||||
|
// fmt.Println(item.IDs)
|
||||||
|
// fmt.Println(item.ResultCount)
|
||||||
|
// fmt.Println(item.Fields)
|
||||||
|
//}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
// 获取标签列表
|
// 获取标签列表
|
||||||
http.HandleFunc("/tags", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/tags", func(w http.ResponseWriter, r *http.Request) {
|
||||||
defer LogComponent(time.Now().UnixNano(), r) // 最后打印日志
|
defer LogComponent(time.Now().UnixNano(), r) // 最后打印日志
|
||||||
@@ -151,185 +422,6 @@ func main() {
|
|||||||
w.Write(json)
|
w.Write(json)
|
||||||
})
|
})
|
||||||
|
|
||||||
type Similar struct {
|
|
||||||
Id int64 `json:"id"`
|
|
||||||
ArticleId int64 `json:"article_id"`
|
|
||||||
Embedding []float32 `json:"embedding"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取相似图片列表
|
|
||||||
http.HandleFunc("/similar", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
defer LogComponent(time.Now().UnixNano(), r) // 最后打印日志
|
|
||||||
id := "8888"
|
|
||||||
// 先查询图片的向量在 mulvis 中是否存在
|
|
||||||
var collection_name = "default" // 图片集合名称
|
|
||||||
result, err := milvusConnection.Client.Query(
|
|
||||||
context.Background(), // ctx
|
|
||||||
collection_name, // CollectionName
|
|
||||||
[]string{}, // PartitionName
|
|
||||||
fmt.Sprintf("id in [%s]", id), // expr
|
|
||||||
[]string{"id", "embedding", "article_id"}, // OutputFields
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: 不存在则重建向量
|
|
||||||
var similar Similar
|
|
||||||
for _, item := range result {
|
|
||||||
if item.Name() == "id" {
|
|
||||||
similar.Id = item.FieldData().GetScalars().GetLongData().GetData()[0]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if item.Name() == "article_id" {
|
|
||||||
similar.ArticleId = item.FieldData().GetScalars().GetLongData().GetData()[0]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if item.Name() == "embedding" {
|
|
||||||
similar.Embedding = item.FieldData().GetVectors().GetFloatVector().Data
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用向量查询相似图片
|
|
||||||
sp, _ := entity.NewIndexIvfFlatSearchParam(64)
|
|
||||||
vectors := []entity.Vector{
|
|
||||||
entity.FloatVector(similar.Embedding),
|
|
||||||
}
|
|
||||||
resultx, err := milvusConnection.Client.Search(
|
|
||||||
context.Background(), // ctx
|
|
||||||
collection_name, // CollectionName
|
|
||||||
nil, // PartitionNames
|
|
||||||
"", // expr
|
|
||||||
[]string{"id", "article_id"}, // OutputFields
|
|
||||||
vectors, // vectors
|
|
||||||
"embedding", // vectorField
|
|
||||||
entity.L2, // entity.MetricType
|
|
||||||
10, // topK
|
|
||||||
sp, // searchParam
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 输出结果
|
|
||||||
for _, item := range resultx {
|
|
||||||
fmt.Println(item.Scores)
|
|
||||||
fmt.Println(item.IDs)
|
|
||||||
fmt.Println(item.ResultCount)
|
|
||||||
fmt.Println(item.Fields)
|
|
||||||
}
|
|
||||||
|
|
||||||
//func printResult(sRet *client.SearchResult) {
|
|
||||||
// randoms := make([]float64, 0, sRet.ResultCount)
|
|
||||||
// scores := make([]float32, 0, sRet.ResultCount)
|
|
||||||
//
|
|
||||||
// var randCol *entity.ColumnDouble
|
|
||||||
// for _, field := range sRet.Fields {
|
|
||||||
// if field.Name() == randomCol {
|
|
||||||
// c, ok := field.(*entity.ColumnDouble)
|
|
||||||
// if ok {
|
|
||||||
// randCol = c
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// for i := 0; i < sRet.ResultCount; i++ {
|
|
||||||
// val, err := randCol.ValueByIdx(i)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Fatal(err)
|
|
||||||
// }
|
|
||||||
// randoms = append(randoms, val)
|
|
||||||
// scores = append(scores, sRet.Scores[i])
|
|
||||||
// }
|
|
||||||
// fmt.Printf("\trandoms: %v, scores: %v\n", randoms, scores)
|
|
||||||
//}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 获取图片信息列表(分页)
|
|
||||||
http.HandleFunc("/images", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
defer LogComponent(time.Now().UnixNano(), r) // 最后打印日志
|
|
||||||
|
|
||||||
// 私域: (自己的图片, 自己的文章, 自己的精选集, 点赞收藏精选集)
|
|
||||||
// 条件查询(模糊搜索, 时间区间, 作者, 标签, 分类, 精选集, 状态, 置顶, 模糊权重)(权重规则:权重指数)
|
|
||||||
// 条件筛选(交集, 并集, 差集, 子集)
|
|
||||||
// 排序
|
|
||||||
// 分页
|
|
||||||
|
|
||||||
// 获取查询条件(忽略空值), 超级简洁写法
|
|
||||||
QueryConditions := func(key string) (list []string) {
|
|
||||||
for _, item := range strings.Split(r.URL.Query().Get(key), ",") {
|
|
||||||
if item != "" {
|
|
||||||
list = append(list, fmt.Sprintf("'%s'", item))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
// 拼接查询条件, 超级简洁写法
|
|
||||||
conditions := ""
|
|
||||||
if authors := QueryConditions("authors"); len(authors) > 0 {
|
|
||||||
conditions += fmt.Sprintf(" AND author IN (%s)", strings.Join(authors, ","))
|
|
||||||
}
|
|
||||||
if tags := QueryConditions("tags"); len(tags) > 0 {
|
|
||||||
conditions += fmt.Sprintf(" AND tag IN (%s)", strings.Join(tags, ","))
|
|
||||||
}
|
|
||||||
if categories := QueryConditions("categories"); len(categories) > 0 {
|
|
||||||
conditions += fmt.Sprintf(" AND categorie IN (%s)", strings.Join(categories, ","))
|
|
||||||
}
|
|
||||||
if sets := QueryConditions("sets"); len(sets) > 0 {
|
|
||||||
conditions += fmt.Sprintf(" AND sets IN (%s)", strings.Join(sets, ","))
|
|
||||||
}
|
|
||||||
if conditions != "" {
|
|
||||||
conditions = strings.Replace(conditions, " AND", "", 1) // 去掉第一个 AND
|
|
||||||
conditions = " WHERE" + conditions // 拼接 WHERE
|
|
||||||
fmt.Println(conditions) // 打印查询条件
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取图片列表
|
|
||||||
var images ListView
|
|
||||||
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"+conditions+" 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" + conditions).Scan(&images.Total)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("获取图片总数失败", err)
|
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否有下一页
|
|
||||||
images.Next = images.Total > images.Page*images.PageSize
|
|
||||||
|
|
||||||
// 将对象转换为有缩进的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
|
// URL 格式: /img/{type}-{id}.{format}?width=320&height=320&fit=cover
|
||||||
http.HandleFunc("/img/", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/img/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
defer LogComponent(time.Now().UnixNano(), r) // 最后打印日志
|
defer LogComponent(time.Now().UnixNano(), r) // 最后打印日志
|
||||||
|
Reference in New Issue
Block a user