用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/Dev-Toolbelt/dev-team-agents --skill multipart-upload命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | multipart-upload |
| description | Chunked file upload — pre-signed URLs, chunk management, retry. |
Use when uploading files > 5 MB or when upload reliability and progress feedback matter.
| Signal | Action |
|---|---|
| File input expected to handle large files (images, video, docs, exports) | Apply this skill |
| S3 / R2 / GCS / Azure Blob storage detected | Apply this skill |
| Upload progress bar or resumable upload required | Apply this skill |
multipart, presigned, chunk anywhere in the codebase | Apply this skill |
Client → POST /uploads/initiate → { uploadId, key }
Client → POST /uploads/presign-chunk → { presignedUrl, partNumber }
Client → PUT presignedUrl (chunk) → ETag from S3
Client → POST /uploads/complete → { url } (final assembled file)
Client → POST /uploads/abort → cleanup on failure
Initiate endpoint
key (UUID + original extension, never user-controlled)Content-Type header aloneuploadIdupload_id, key, user_id, status: pending, expires_at)Pre-sign chunk endpoint
uploadId belongs to the requesting user (ownership check)Complete endpoint
[{ partNumber, ETag }] array from clientcompleteMultipartUpload with parts liststatus: complete, urlAbort endpoint
abortMultipartUploadexpires_at)Use a single pre-signed PUT URL — skip multipart entirely.
private/ prefix; serve via CDN with signed cookies — never public bucket URLsstatus: availableconst CHUNK_SIZE = 10 * 1024 * 1024 // 10 MB — adjust to latency/reliability trade-off
async function uploadFile(file: File) {
const totalChunks = Math.ceil(file.size / CHUNK_SIZE)
const { uploadId, key } = await api.initiateUpload({ filename: file.name, size: file.size })
const parts: { partNumber: number; ETag: string }[] = []
for (let i = 0; i < totalChunks; i++) {
const chunk = file.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE)
const { presignedUrl } = await api.presignChunk({ uploadId, partNumber: i + 1 })
const res = await fetch(presignedUrl, { method: 'PUT', body: chunk })
parts.push({ partNumber: i + , : res..()! })
(.(((i + ) / totalChunks) * ))
}
api.({ uploadId, key, parts })
}
XMLHttpRequest.upload.onprogress for granular reporting(completedChunks / totalChunks) * 100 for a simple barnavigator.sendBeacon to clean up server-side# Bucket CORS for multipart upload
CorsConfiguration:
CorsRules:
- AllowedOrigins: ["https://yourdomain.com"]
AllowedMethods: [PUT, GET]
AllowedHeaders: ["*"]
ExposeHeaders: [ETag]
MaxAgeSeconds: 3600
{ "AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 1 } }
AllowedMethods: [PUT] in CORS — R2 does not require ExposeHeaders: [ETag] explicitlyresumable upload type for files > 5 MBstageBlock / commitBlockList — analogous to S3 partsSTORAGE_BUCKET=
STORAGE_REGION=
STORAGE_PRESIGN_EXPIRY_SECONDS=900
UPLOAD_MAX_BYTES=524288000 # 500 MB
UPLOAD_ALLOWED_TYPES=image/jpeg,image/png,application/pdf