api/service/image_asset/README.md
图片资源服务用于处理文档转换后 Markdown 内容中的 /static/ 图片链接,将其下载到本地存储并替换为预览链接。
/static/ 图片链接DOC_CONVERT_BASE_URL: 文档转换服务的基础 URL(如: http://192.168.1.218:5022)REDIS_ENABLED: 必须为 true(队列依赖 Redis)service/image_asset/
├── types.go # 数据结构定义
├── queue.go # Redis 队列管理
├── orchestrator.go # 编排器(解析、替换)
├── downloader.go # 下载器(限流、重试)
├── service.go # 服务封装
├── orchestrator_test.go # 单元测试
└── README.md # 文档说明
InitImageAssetService(): 初始化服务StartImageDownloadWorkers(ctx, workerCount, rateLimit): 启动下载工作器StartImageReplacementAsync(eid, fileID, userID, fileBodyID, content): 异步处理图片替换QueueManager: Redis 队列管理器Orchestrator: 内容解析和替换编排器Downloader: 图片下载和存储处理器go test ./service/image_asset/... -v
go run test_image_service.go

[文档链接](/static/20250829/uuid/doc.pdf)


[文档链接](http://192.168.1.218:9002/api/preview/def456.pdf)

graph LR
C[Producer/触发者] -->|Enqueue| Q[QueueManager
Redis 队列]
Q -->|Dequeue| W[Downloader.Worker]
W -->|限流等待| RL[RateLimiter
(Ticker)]
W -->|HTTP GET 图片| H[HTTP Server]
H -->|200 + Body| W
W -->|Save(body, key)| S[storage.StorageInstance]
W -->|By PreviewKey 获取| M[model.UploadFile]
W -->|UpdateSizeAndMimeType| DB[(DB)]
W -->|MarkAsCompleted| DB
W -->|AckTask| Q
%% 异常路径(注释说明)
classDef error fill:#fdd,stroke:#f99,color:#900;
E1[HTTP 错误/超时]:::error
E2[存储失败]:::error
E3[DB 更新失败]:::error
W -.-> E1
W -.-> E2
W -.-> E3
sequenceDiagram
participant C as Client/Producer
participant Q as QueueManager
participant W as Downloader.Worker
participant R as RateLimiter (Ticker)
participant H as HTTP Server
participant S as Storage
participant M as Model(DB)
C->>Q: Enqueue(ImageDownloadTask)
W->>Q: Dequeue()
alt 有任务
Q-->>W: ImageDownloadTask
W->>R: wait token
R-->>W: token
W->>H: GET AbsoluteURL
H-->>W: 200 + Body
W->>S: Save(body, storageKey)
S-->>W: ok
W->>M: GetNoAuthUploadFileByEidAndPreviewKey(previewKey)
M-->>W: UploadFile
W->>M: UpdateSizeAndMimeType(len(body), contentType)
M-->>W: ok
W->>M: MarkAsCompleted()
M-->>W: ok
W->>Q: AckTask(success=true)
Q-->>W: acked
else 无任务
Q-->>W: queue is empty
end
opt 异常分支
alt HTTP 非 200/读取失败
W->>Q: FailTask(error)
else Save 存储失败
W->>Q: FailTask(error)
else DB 更新失败(size/mime/mark)
W->>W: 记录错误日志(不阻塞已下载结果)
W->>Q: AckTask(success=true)
end
end
len(body),并以 int64(len(body)) 传递。uploadFile.UpdateSizeAndMimeType(size, contentType) 将 size 和(当不为空时)MimeType 写入数据库;MarkAsCompleted() 仅更新状态与处理时间。size 是否一致。Content-Type 为空时,不覆盖已有 MimeType;非空则更新。size=0,优先检查模型层是否正确调用 UpdateSizeAndMimeType,以及数据库更新是否成功。