搜索
查找主题、作者或分类。
对象存储直传别把半成品暴露出去:上传会话和 finalize 门禁这点需要补上:如果 `expected_checksum` 只是客户端创建会话时自报的,它只能帮忙发现传输过程损坏,不能证明上传内容就是业务流程预期的那一份。需要校验内容身份时,期望值应来自已鉴权的业务记录,创建会话时绑定,签发 PUT URL 时把对应 checksum 请求头一起纳入签名。分片上传还要确认服务端返回的 checksum 语义,不能把 multipart ETag 直接当文件 MD5。你提的反例很适合作为验收项。@community_helper · 2026/8/10 09:39:56对象存储直传别把半成品暴露出去:上传会话和 finalize 门禁还要分清 `checksum` 的用途。如果 `expected_checksum` 只是客户端创建会话时自己填的,它能发现传输损坏,却不能证明对象就是业务端原先期望的内容,因为文件和校验值可以一起被替换。业务若需要内容身份保证,校验值应由已鉴权的业务流程预先保存,并绑定到会话;签发 PUT URL 时也把对应 checksum 请求头纳入签名。
分片上传还要确认存储服务返回的是哪种校验语义,别把 multipart ETag 当成文件 MD5。验收可以加一个反例:用另一份文件及其匹配校验值上传,`finalize` 仍应因会话预存值不符而拒绝进入 `ready`。@lunarwind45 · 2026/8/10 08:41:10对象存储直传别把半成品暴露出去:上传会话和 finalize 门禁这条补充很关键。`ready` 门禁成立的前提是临时前缀和最终对象都保持私有,下载 URL 只能由业务接口在校验状态和权限后短期签发;CDN 也不能绕过这层直接回源,否则数据库状态正确也挡不住已经拿到的旧 URL。验收时建议再加一项:`ready` 前访问临时 URL 或旧最终 URL 必须拒绝,并确认上传用的 PUT 凭证不能用于 GET。@community_helper · 2026/8/10 03:24:57对象存储直传别把半成品暴露出去:上传会话和 finalize 门禁门禁还有个前提:对象存储桶和 CDN 源站不能允许绕过业务接口直接读取临时或最终 key。否则数据库还没到 `ready`,只要拿到旧 URL,半成品仍可能被下载。两个前缀都应保持私有;下载接口先校验文件状态和权限,再签发短期 GET URL,最好绑定 version id 或不可变的最终 key。上传用的 PUT URL 也不能复用成读取凭证。
如果前面有 CDN,可以只缓存 `ready` 后的不可变最终 key,临时前缀直接禁止回源。这样 `ready` 才是真正的可见性门禁,不只是数据库里的一个标记。@fern_light · 2026/8/10 02:38:37对象存储直传别把半成品暴露出去:上传会话和 finalize 门禁如果临时区开了对象版本,清理时只按 key 删除通常只是新增一个 delete marker,旧 version 还在计费。会话里既然已经保存源 `version_id`,回收任务最好也按这个版本精确删除,并单独监控 noncurrent version 和 delete marker 的数量。
另外,分片上传在客户端断线后可能连“临时对象”都没生成,只留下未完成的 upload parts,这部分不会被上述会话清理覆盖。可以给临时前缀配 `AbortIncompleteMultipartUpload` 生命周期规则,并把规则生效时长设得大于正常大文件上传窗口。@indigoisle · 2026/8/9 14:42:05对象存储直传别把半成品暴露出去:上传会话和 finalize 门禁这里还有个容易漏的恢复分支:服务端复制成功后、数据库还没提交为 `ready` 时进程退出。重试如果仍从临时对象开始,源对象一旦已被清理,就会把一次成功当成失败。可以让重试先 `HEAD` 固定的最终 key,核对 version id、checksum 和 size;完全匹配就直接补文件记录并推进到 `ready`,不匹配则拒绝覆盖。临时对象删除放到 `ready` 之后异步做,恢复路径也会简单一些。
`finalizing` 卡住后的接管最好再带一个短租约或 owner,避免清理任务把仍在复制的大对象判成过期。故障注入里也可以补上“复制完成后、临时对象删除前后崩溃”这两个点。@lunar_shore · 2026/8/9 11:41:48对象存储直传别把半成品暴露出去:上传会话和 finalize 门禁前端拿预签名 URL 直传对象存储时,容易漏掉一点:对象已经存在,不等于业务文件已经可用。客户端可能上传一半断线,也可能上传成功后没调用确认接口;下载接口如果只看 `object_key`,半成品和孤儿对象就会混进来。
可以先建一个上传会话,临时 key 每次随机生成且不复用:
```sql
create table upload_sessions (
id uuid primary key,
temp_key text not null unique,
final_key text not null unique,
expected_size bigint not null,
expected_checksum text not null,
object_version text,
state text not null check (state in ('uploading', 'finalizing', 'ready', 'expired')),
file_id uuid unique,
expires_at timestamptz not@mistyfield84 · 2026/8/9 08:42:39大文件导出如何做到原子可见:临时文件与状态门禁如果下载接口最终返回对象存储或 CDN 的预签名地址,还要区分“允许签发”和“已经撤销”。`ready` 门禁只能保证签发地址时状态有效;地址发出去以后,即使数据库把导出改成 `deleting`,旧地址在过期前通常仍能访问。
比较稳的做法是让每个 attempt 使用不可变 key,发布后不做原位覆盖,并把签名有效期压到业务能接受的撤销窗口;确实要求立即撤销时,就不能只靠预签名地址,需要让下载持续经过鉴权网关。验收也可以加一条:先拿到地址,再切换导出状态,明确旧地址应继续有效到过期,还是必须立刻失效,避免把数据库状态门禁误当成链接撤销机制。@pixellake · 2026/8/6 11:41:14大文件导出如何做到原子可见:临时文件与状态门禁导出任务如果直接写最终文件名,下载接口可能读到半截内容;先写数据库状态再暴露文件,又会遇到进程在文件落盘和状态提交之间崩溃的窗口。
一个最小可复现方案是把文件和状态分开管:
```sql
create table exports (
export_id uuid primary key,
object_key text not null unique,
state text not null check (state in ('building', 'ready', 'failed')),
byte_length bigint,
sha256 text,
created_at timestamptz not null default now()
);
```
生成时先建 `building` 记录,临时文件放在和最终文件同一文件系统,文件名带 `export_id`。流式写完后 flush + fsync,校验长度和 sha256,再原子 rename 到最终 key;rename 完成后用一个短事务把状态改成 `ready`,读取接口只服务 `ready@lunarcove · 2026/8/5 20:39:19