mirror of
https://git.fightbot.fun/hxuanyu/BingPaper.git
synced 2026-02-15 07:19:33 +08:00
增加更多分辨率图像的拉取
This commit is contained in:
@@ -157,7 +157,7 @@ func Init(configPath string) error {
|
||||
v.SetDefault("api.mode", "local")
|
||||
v.SetDefault("cron.enabled", true)
|
||||
v.SetDefault("cron.daily_spec", "0 10 * * *")
|
||||
v.SetDefault("retention.days", 30)
|
||||
v.SetDefault("retention.days", 0)
|
||||
v.SetDefault("db.type", "sqlite")
|
||||
v.SetDefault("db.dsn", "data/bing_paper.db")
|
||||
v.SetDefault("storage.type", "local")
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"BingPaper/internal/config"
|
||||
"BingPaper/internal/model"
|
||||
@@ -40,7 +41,7 @@ type ImageMetaResp struct {
|
||||
// @Summary 获取今日图片
|
||||
// @Description 根据参数返回今日必应图片流或重定向
|
||||
// @Tags image
|
||||
// @Param variant query string false "分辨率 (UHD, 1920x1080, 1366x768)" default(UHD)
|
||||
// @Param variant query string false "分辨率 (UHD, 1920x1080, 1366x768, 1280x720, 1024x768, 800x600, 800x480, 640x480, 640x360, 480x360, 400x240, 320x240)" default(UHD)
|
||||
// @Param format query string false "格式 (jpg)" default(jpg)
|
||||
// @Produce image/jpeg
|
||||
// @Success 200 {file} binary
|
||||
@@ -144,19 +145,53 @@ func GetByDateMeta(c *gin.Context) {
|
||||
|
||||
// ListImages 获取图片列表
|
||||
// @Summary 获取图片列表
|
||||
// @Description 分页获取已抓取的图片元数据列表
|
||||
// @Description 分页获取已抓取的图片元数据列表。支持分页(page, page_size)、限制数量(limit)和按月份过滤(month, 格式: YYYY-MM)。
|
||||
// @Tags image
|
||||
// @Param limit query int false "限制数量" default(30)
|
||||
// @Param limit query int false "限制数量 (如果不使用分页)" default(30)
|
||||
// @Param page query int false "页码 (从1开始)"
|
||||
// @Param page_size query int false "每页数量"
|
||||
// @Param month query string false "按月份过滤 (格式: YYYY-MM)"
|
||||
// @Produce json
|
||||
// @Success 200 {array} ImageMetaResp
|
||||
// @Router /images [get]
|
||||
func ListImages(c *gin.Context) {
|
||||
limitStr := c.DefaultQuery("limit", "30")
|
||||
var limit int
|
||||
fmt.Sscanf(limitStr, "%d", &limit)
|
||||
limitStr := c.Query("limit")
|
||||
pageStr := c.Query("page")
|
||||
pageSizeStr := c.Query("page_size")
|
||||
month := c.Query("month")
|
||||
|
||||
images, err := image.GetImageList(limit)
|
||||
// 记录请求参数,便于排查过滤失效问题
|
||||
util.Logger.Debug("ListImages parameters",
|
||||
zap.String("month", month),
|
||||
zap.String("page", pageStr),
|
||||
zap.String("page_size", pageSizeStr),
|
||||
zap.String("limit", limitStr))
|
||||
|
||||
var limit, offset int
|
||||
|
||||
if pageStr != "" && pageSizeStr != "" {
|
||||
page, _ := strconv.Atoi(pageStr)
|
||||
pageSize, _ := strconv.Atoi(pageSizeStr)
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 {
|
||||
pageSize = 30
|
||||
}
|
||||
limit = pageSize
|
||||
offset = (page - 1) * pageSize
|
||||
} else {
|
||||
if limitStr == "" {
|
||||
limit = 30
|
||||
} else {
|
||||
limit, _ = strconv.Atoi(limitStr)
|
||||
}
|
||||
offset = 0
|
||||
}
|
||||
|
||||
images, err := image.GetImageList(limit, offset, month)
|
||||
if err != nil {
|
||||
util.Logger.Error("ListImages service call failed", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -142,36 +142,47 @@ func (f *Fetcher) processImage(ctx context.Context, bingImg BingImage) error {
|
||||
}
|
||||
|
||||
// 保存各种分辨率
|
||||
variants := []struct {
|
||||
targetVariants := []struct {
|
||||
name string
|
||||
width int
|
||||
height int
|
||||
}{
|
||||
{variantName, 0, 0}, // 原图 (UHD 或 1080p)
|
||||
{"1920x1080", 1920, 1080},
|
||||
{"1366x768", 1366, 768},
|
||||
{"1280x720", 1280, 720},
|
||||
{"1024x768", 1024, 768},
|
||||
{"800x600", 800, 600},
|
||||
{"800x480", 800, 480},
|
||||
{"640x480", 640, 480},
|
||||
{"640x360", 640, 360},
|
||||
{"480x360", 480, 360},
|
||||
{"400x240", 400, 240},
|
||||
{"320x240", 320, 240},
|
||||
}
|
||||
|
||||
for _, v := range variants {
|
||||
// 如果是探测到的最高清版本,且我们已经有了数据,直接使用
|
||||
var currentImgData []byte
|
||||
if v.width == 0 {
|
||||
currentImgData = imgData
|
||||
} else {
|
||||
resized := imaging.Fill(srcImg, v.width, v.height, imaging.Center, imaging.Lanczos)
|
||||
buf := new(bytes.Buffer)
|
||||
if err := jpeg.Encode(buf, resized, &jpeg.Options{Quality: 90}); err != nil {
|
||||
util.Logger.Warn("Failed to encode jpeg", zap.String("variant", v.name), zap.Error(err))
|
||||
continue
|
||||
}
|
||||
currentImgData = buf.Bytes()
|
||||
// 首先保存原图 (UHD 或 1080p)
|
||||
if err := f.saveVariant(ctx, &dbImg, variantName, "jpg", imgData); err != nil {
|
||||
util.Logger.Error("Failed to save original variant", zap.String("variant", variantName), zap.Error(err))
|
||||
}
|
||||
|
||||
for _, v := range targetVariants {
|
||||
// 如果目标分辨率就是原图分辨率,则跳过(已经保存过了)
|
||||
if v.name == variantName {
|
||||
continue
|
||||
}
|
||||
|
||||
resized := imaging.Fill(srcImg, v.width, v.height, imaging.Center, imaging.Lanczos)
|
||||
buf := new(bytes.Buffer)
|
||||
if err := jpeg.Encode(buf, resized, &jpeg.Options{Quality: 100}); err != nil {
|
||||
util.Logger.Warn("Failed to encode jpeg", zap.String("variant", v.name), zap.Error(err))
|
||||
continue
|
||||
}
|
||||
currentImgData := buf.Bytes()
|
||||
|
||||
// 保存 JPG
|
||||
if err := f.saveVariant(ctx, &dbImg, v.name, "jpg", currentImgData); err != nil {
|
||||
util.Logger.Error("Failed to save variant", zap.String("variant", v.name), zap.Error(err))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 保存今日额外文件
|
||||
@@ -241,13 +252,13 @@ func (f *Fetcher) saveDailyFiles(srcImg image.Image, originalData []byte) {
|
||||
return
|
||||
}
|
||||
|
||||
// daily.jpeg (quality 95)
|
||||
// daily.jpeg (quality 100)
|
||||
jpegPath := filepath.Join(localRoot, "daily.jpeg")
|
||||
fJpeg, err := os.Create(jpegPath)
|
||||
if err != nil {
|
||||
util.Logger.Error("Failed to create daily.jpeg", zap.Error(err))
|
||||
} else {
|
||||
jpeg.Encode(fJpeg, srcImg, &jpeg.Options{Quality: 95})
|
||||
jpeg.Encode(fJpeg, srcImg, &jpeg.Options{Quality: 100})
|
||||
fJpeg.Close()
|
||||
}
|
||||
|
||||
|
||||
@@ -86,12 +86,29 @@ func GetImageByDate(date string) (*model.Image, error) {
|
||||
return &img, err
|
||||
}
|
||||
|
||||
func GetImageList(limit int) ([]model.Image, error) {
|
||||
func GetImageList(limit int, offset int, month string) ([]model.Image, error) {
|
||||
var images []model.Image
|
||||
db := repo.DB.Order("date desc").Preload("Variants")
|
||||
if limit > 0 {
|
||||
db = db.Limit(limit)
|
||||
tx := repo.DB.Model(&model.Image{})
|
||||
|
||||
if month != "" {
|
||||
// 增强过滤:确保只处理 YYYY-MM 格式,防止注入或非法字符
|
||||
// 这里简单处理:只要不为空就增加 LIKE 过滤
|
||||
util.Logger.Debug("Filtering images by month", zap.String("month", month))
|
||||
tx = tx.Where("date LIKE ?", month+"%")
|
||||
}
|
||||
|
||||
tx = tx.Order("date desc").Preload("Variants")
|
||||
|
||||
if limit > 0 {
|
||||
tx = tx.Limit(limit)
|
||||
}
|
||||
if offset > 0 {
|
||||
tx = tx.Offset(offset)
|
||||
}
|
||||
|
||||
err := tx.Find(&images).Error
|
||||
if err != nil {
|
||||
util.Logger.Error("Failed to get image list", zap.Error(err), zap.String("month", month))
|
||||
}
|
||||
err := db.Find(&images).Error
|
||||
return images, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user