feat: 单场秀内的图片进度也上报(x/y 张)

一场秀几十到几百张图,按批处理要十几分钟,只报场次会让进度十几分钟不动。
media.UploadAllProgress 每批回调一次,spider 据此把「正在抓 X(32/50 张)」报给后台。
This commit is contained in:
toom1996
2026-10-25 21:02:52 +08:00
parent fb9b6c4f6e
commit 1ead57dd22
2 changed files with 20 additions and 3 deletions

View File

@ -77,6 +77,15 @@ func New(client *ingest.Client, prefix string, concurrency int) *Uploader {
// UploadAll 并发完成「下载 → 生成 key → 预签名 → PUT」,返回与 urls 下标一一对应的结果。
// 单张失败不影响其他张:该下标 Err 非空,调用方据此对这张回退成 URL 上报。
func (u *Uploader) UploadAll(ctx context.Context, urls []string) []Result {
return u.UploadAllProgress(ctx, urls, nil)
}
// UploadAllProgress 与 UploadAll 相同,但每完成一批回调一次 onBatch(done, total)。
//
// 用途:一场秀几十到几百张图,按批处理要跑十几分钟。
// 上层靠这个回调把「传到第几张」显示到后台,否则进度只能一场一跳,
// 中间十几分钟界面上什么都看不出。
func (u *Uploader) UploadAllProgress(ctx context.Context, urls []string, onBatch func(done, total int)) []Result {
results := make([]Result, len(urls))
if len(urls) == 0 {
return results
@ -93,6 +102,9 @@ func (u *Uploader) UploadAll(ctx context.Context, urls []string) []Result {
end = len(urls)
}
u.uploadBatch(ctx, urls, results, start, end)
if onBatch != nil {
onBatch(end, len(urls))
}
}
return results
}

View File

@ -2,6 +2,7 @@ package spider
import (
"context"
"fmt"
"log"
"regexp"
"strconv"
@ -101,7 +102,7 @@ const maxShowConcurrency = 2
//
// 返回 true 表示全部成功;false 表示有失败项 —— 失败的图仍保留原始 URL,
// 后端见到「没有 key」就用 URL 自己下载,所以整场不会因为几张图失败而报废。
func (s *VogueSpider) uploadLookMedia(ctx context.Context, looks []ingest.RunwayLook) bool {
func (s *VogueSpider) uploadLookMedia(ctx context.Context, title string, looks []ingest.RunwayLook) bool {
type ref struct{ look, detail int } // detail = -1 表示主图
urls := make([]string, 0, len(looks)*2)
@ -123,7 +124,11 @@ func (s *VogueSpider) uploadLookMedia(ctx context.Context, looks []ingest.Runway
return true
}
res := s.Media.UploadAll(ctx, urls)
// 每传完一批把「这场传到第几张」报给后台:一场秀按批要跑十几分钟,
// 只报场次的话界面会十几分钟不动,看着像卡死。
res := s.Media.UploadAllProgress(ctx, urls, func(done, total int) {
s.reportProgress(fmt.Sprintf("%s(%d/%d 张)", title, done, total), false)
})
okAll := true
for k, r := range res {
if r.Err != nil || r.Key == "" {
@ -456,7 +461,7 @@ func (s *VogueSpider) getDetail(brandUID string, info gjson.Result) {
// 任一张失败不影响整场:失败的图仍带原始 URL,由后端兜底下载。
if s.Media != nil && len(looks) > 0 {
log.Printf("[media] 开始直传 %d 个 look / %d 张图", len(looks), totalImages)
okAll := s.uploadLookMedia(context.Background(), looks)
okAll := s.uploadLookMedia(context.Background(), hed, looks)
if okAll {
log.Printf("[media] 已直传 %d 个 look / %d 张图,后端将跳过下载", len(looks), totalImages)
} else {