feat(s3): 图片上传到 S3——设置/自动上传/右键单张/批量上传(docs/30)
Rust 新增 s3.rs:SigV4 签名 + PUT Object(reqwest blocking+rustls, 签名对照 AWS 官方示例向量逐字一致;同份代码对本地模拟 S3 端到端 实测通过)。命令 s3_upload_image / s3_test_connection(总数 30 对账)。 配置存 UiState.s3(本机偏好),设置弹窗含测试连接与自动上传开关。 未上传判定 = src 非 http/data/blob 的本地引用;上传成功后同 src 的 图片节点一次事务回换为 S3 地址,本地 .assets 文件保留。 入口:粘贴/插入后自动上传回换(扑空重试一次、失败必提示);右键 命中本地图片多一项「上传到 S3」;文件菜单 + 状态栏批量上传带进度 弹窗。验证:vitest 133+2、tsc、构建通过,设置弹窗截图核对。
This commit is contained in:
64
docs/30-S3图片上传.md
Normal file
64
docs/30-S3图片上传.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# docs/30 — S3 图片上传
|
||||
|
||||
需求(2026-11-15 用户提出):①设置里能配 S3 并有「自动上传图片」开关;
|
||||
②未上传的图片右键要有「上传到 S3」;③整个文档要有批量检测未上传图片
|
||||
并上传的按钮。
|
||||
|
||||
## 设计
|
||||
|
||||
- **协议层在 Rust**(`src-tauri/src/s3.rs`):AWS SigV4 签名 + PUT Object,
|
||||
reqwest(blocking + rustls)。配置随每次调用从前端传入,Rust 不落盘
|
||||
保存密钥。命令 2 个(总数 30 与 lib.rs 注册对账):`s3_upload_image`、
|
||||
`s3_test_connection`(对桶发签名 HEAD,按 200/403/404 给可读结论)。
|
||||
- **寻址风格**:Endpoint 留空 = AWS S3 虚拟主机风格
|
||||
`https://{bucket}.s3.{region}.amazonaws.com/{key}`;填了自定义
|
||||
Endpoint(MinIO / R2 / OSS 等 S3 兼容服务)走路径风格
|
||||
`{endpoint}/{bucket}/{key}`。对象键 = 前缀 + 原文件名(同名覆盖,
|
||||
重复上传幂等)。配了「自定义访问域名」时回填文档的是该域名拼的地址。
|
||||
- **配置存储**:进 UiState.s3(本机偏好库 SQLite/localStorage),字段
|
||||
endpoint/region/bucket/accessKey/secretKey/prefix/publicBase/autoUpload;
|
||||
加载时与默认值深合并。设置弹窗在 文件 → S3 上传设置…,带「测试连接」。
|
||||
弹窗里已明示:密钥只保存在本机设置里,不写进文档、不会被 Git 同步带走。
|
||||
- **「未上传」判定**:图片 src 不是 http(s)/data/blob 即本地引用
|
||||
(`isLocalImageSrc`)。上传成功后把编辑器里所有同 src 的图片节点
|
||||
一次事务换成 S3 地址(`replaceImageSrc`,同图多处引用一并换),文档
|
||||
随之变脏、走既有自动保存落盘。本地 .assets 文件保留不删(删了断掉
|
||||
离线打开时的图,且用户可能还要本地备份)。
|
||||
|
||||
## 三个入口
|
||||
|
||||
1. **自动上传**(开关在 S3 设置里):粘贴/拖入(handleImageFile 落盘后)
|
||||
与「插入图片」(copyToAssets 后)触发后台上传+回换;粘贴建节点是
|
||||
异步的,第一次回换扑空时 900ms 后重试一次;再扑空或上传失败都给
|
||||
提示(flash),不静默、本地引用保留。
|
||||
2. **右键单张**:编辑区右键命中 <img> 时经 `imageSrcForElement`
|
||||
(posAtDOM 反查节点)拿到文档 src;本地图时菜单多一项「上传到 S3」。
|
||||
未配置 S3 时点它先弹设置弹窗并提示。
|
||||
3. **批量**:文件 →「上传文档图片到 S3…」+ 状态栏按钮(当前文档有未
|
||||
上传本地图片时出现,带张数)。扫描走编辑器 `listImages()`(PM 文档
|
||||
遍历、去重),逐张上传回换,进度弹窗实时显示 第 N/总 张与当前文件
|
||||
名,结束汇总成功/失败明细。源码模式下不可用(菜单禁用、状态栏不
|
||||
计数),提示切回即时渲染。
|
||||
|
||||
## 验证
|
||||
|
||||
- **签名算法**:独立小 crate 里对照 AWS 官方文档示例(IAM ListUsers,
|
||||
20150830T123600Z)——算出的 Signature 与官方值
|
||||
`5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7`
|
||||
逐字一致;UTC 时间换算(Hinnant civil 算法)与空负载哈希一并断言。
|
||||
- **协议端到端**:把随产品发货的同一份 s3.rs 放进独立 crate,对本地
|
||||
TCP 模拟 S3 跑真实请求:PUT 路径风格、中文文件名百分号编码、
|
||||
x-amz-content-sha256 与请求体哈希一致、Authorization 头结构、
|
||||
自定义访问域名回填、HEAD 桶测试连接、空配置校验,2 例全过。
|
||||
- **前端**:vitest 133+2(新增 s3.test 路径/判定、editor-images 收集/
|
||||
回换/元素反查、s3-modal 保存载荷、右键菜单图片项);tsc 与构建通过;
|
||||
设置弹窗无头浏览器截图核对(七个字段、开关、三按钮齐全)。
|
||||
- **Cargo.lock 已更新**(reqwest 0.12.28 等,本机 cargo fetch 完成)。
|
||||
|
||||
## 待真机验证(Windows)
|
||||
|
||||
- Rust 完整构建(新增 reqwest/sha2/hmac 依赖)与真实 S3/兼容服务联调:
|
||||
填真实配置 → 测试连接 → 粘贴图片自动上传 → 右键单张 → 批量上传,
|
||||
并在桶里核对对象与文档回填地址可公开访问(桶需允许公开读或配 CDN)。
|
||||
- 注意:签名时钟用系统 UTC 时间,本机时钟偏差过大会被 S3 拒绝
|
||||
(报错会带回 S3 的 Code/Message,按提示校时即可)。
|
||||
Reference in New Issue
Block a user