Agent skill

File Upload

by Rain-kl in Rain-kl/OpenFlare

Wavelet 项目专用:当业务需要上传文件、读取已上传文件、在 Worker/任务中程序化摄取字节流、选择存储引擎能力、或排查 wuploads / 文件统计异常时必须使用。本技能指导 storage 与 upload 分层、upload.Ingest 策略选型、前后端接入与禁止旁路写表。

Apache-2.0Auto-check passedBackend & APIs

Install File Upload

skills CLI
$ npx skills add Rain-kl/OpenFlare --skill file-upload -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install Rain-kl/OpenFlare file-upload --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/Rain-kl/OpenFlare.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/file-upload .claude/skills/file-upload && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
file-upload
GitHub stars
288
Token cost
~1.7k tokens
SKILL.md length
338 words
Files
1
Skills in repo
12
Repo updated
First seen
Licence
Apache-2.0

At a glance

Wavelet 项目专用:当业务需要上传文件、读取已上传文件、在 Worker/任务中程序化摄取字节流、选择存储引擎能力、或排查 wuploads / 文件统计异常时必须使用。本技能指导 storage 与 upload 分层、upload.Ingest 策略选型、前后端接入与禁止旁路写表。

  • Works in 4 steps: 前端 POST /api/v1/upload → 获得 upload.id → 业务 API 接收 upload_id,用… → (可选)校验 upload.Type 是否为预期业务类型 → …
  • Tasks that involve File uploads and storage
  • SKILL.md covers 架构分层(必须理解), 核心防线(Guardrails), Ingest 策略选型(Policy Decision) and 后端:程序化上传(Worker / 业务逻辑), plus 6 more sections
  • Calls make and go

What it does

File Upload is an agent skill from Rain-kl/OpenFlare. Wavelet 项目专用:当业务需要上传文件、读取已上传文件、在 Worker/任务中程序化摄取字节流、选择存储引擎能力、或排查 wuploads / 文件统计异常时必须使用。本技能指导 storage 与 upload 分层、upload.Ingest 策略选型、前后端接入与禁止旁路写表。

Its SKILL.md is about 1.7k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Backend & APIs, covering File uploads and storage. It works with Cloudflare. The repository describes itself as: OpenFlare is an open-source CDN orchestration and edge security platform. It supports reverse proxy, centralized configuration synchronization, in-network tunneling (Tunnels)… The licence is Apache-2.0.

When your agent uses it

  • Tasks that involve File uploads and storage

Example prompts

  • “/file-upload”

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. 前端 POST /api/v1/upload → 获得 upload.id
  2. 业务 API 接收 upload_id,用 repository.GetActiveUploadByID 校验存在且 status 为 active
  3. (可选)校验 upload.Type 是否为预期业务类型
  4. 将 upload_id 写入业务表字段(如 cover_file_id)

What it can do on your machine

Read from SKILL.md and the folder at commit 7c2304d. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • make
    • go

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

File Upload loads about 1.7k tokens when it runs. Until then it costs about 40 tokens; SKILL.md has 338 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~40
When it runs · the whole SKILL.md, loaded when a task matches
~1.7k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from Rain-kl/OpenFlare at commit 7c2304d, republished under its Apache-2.0 licence (© Rain-kl). 338 words, ~1,677 tokens.

Download SKILL.mdSave it as .claude/skills/file-upload/SKILL.md (or your agent's skills folder).
name
file-upload
description
Wavelet 项目专用:当业务需要上传文件、读取已上传文件、在 Worker/任务中程序化摄取字节流、选择存储引擎能力、或排查 w_uploads / 文件统计异常时必须使用。本技能指导 storage 与 upload 分层、upload.Ingest 策略选型、前后端接入与禁止旁路写表。

存储引擎与文件上传开发规范

本技能是 Wavelet 文件上传与对象存储的唯一开发指导。开始开发前先阅读仓库根目录 AGENTS.md,遵守项目级核心规则。


架构分层(必须理解)

Wavelet 将「对象存储」与「上传业务」分为两层,禁止混用职责:

层级包路径职责业务是否直接调用
对象存储引擎internal/infra/objectstoreBackend 接口:Put / Get / Delete / Test;按配置切换 Local / S3 / R2 / OSS / WebDAV禁止(仅 upload 域内部使用)
上传域服务internal/apps/uploadw_uploads 记录、权限、秒传、统计、文件服务、upload.Ingest必须
上传 HTTP 入口internal/apps/upload/handlerPOST /api/v1/upload 等 multipart 接口前端 / 用户侧上传
文件访问internal/apps/upload/filesrvGET /f/:id 流式响应、访问控制、图片 WebP 压缩展示 / 下载
text
业务模块 ──► upload.Ingest / upload.Remove(唯一写入门禁)
                ├── storage.Backend.Put/Get/Delete
                ├── repository.CreateUpload(仅 upload 内部)
                └── RecordUploadStatsAdd/Remove(ingest 内置,禁止业务直调)

核心防线(Guardrails)

以下写法一律禁止:

go
// ❌ 业务包直接写 blob
storage.Active(ctx); backend.Put(...)

// ❌ 旁路写 w_uploads
db.DB(ctx).Create(&model.Upload{})
repository.CreateUpload(ctx, upload)   // 仅 internal/apps/upload 允许

// ❌ 手动维护统计
upload.ApplyUploadStatsAdd(ctx, upload)  // 已 Deprecated

// ❌ 业务表存物理路径
invoice.FilePath = "uploads/2026/01/02/123.pdf"

正确做法:业务表只存 upload_id(uint64 / JSON string),通过 /f/{id} 或 upload.OpenStoredObject 访问。


Ingest 策略选型(Policy Decision)

根据场景选择 upload.Ingest 的 Policy:

场景Policy哈希命中时未命中时典型调用方
用户 HTTP 上传(含秒传)PolicyDedupNewRecord复用 path,新建记录 + 统计写 blob + 新建记录 + 统计handler.UploadFile(已内置)
Worker 生成全新文件PolicyCreate不查重,始终写 blob + 记录同左报表导出、定时生成
镜像 / 去重摄取(Pixez)PolicyResolveExisting直接返回已有记录,不建新记录、不加统计写 blob + 新建记录 + 统计异步镜像任务
业务只需引用已有文件不调 Ingest——业务 API 校验 upload_id 即可
Result 字段含义
字段含义
Created是否新建了 w_uploads 记录
Stored是否写入了新 blob
Resolved是否通过哈希解析到已有记录(仅 PolicyResolveExisting)

后端:程序化上传(Worker / 业务逻辑)

标准模板

在 logics.go(接受 context.Context,不依赖 *gin.Context)中调用:

go
import (
    "bytes"

    "github.com/Rain-kl/Wavelet/internal/apps/upload"
    "github.com/Rain-kl/Wavelet/internal/model"
)

func ingestMirrorFile(ctx context.Context, userID uint64, data []byte, hash, filename, mime, ext string) (model.Upload, error) {
    accessMode := 1
    result, err := upload.Ingest(ctx, upload.IngestRequest{
        UserID:     userID,
        Reader:     bytes.NewReader(data),
        Size:       int64(len(data)),
        FileName:   filename,
        MimeType:   mime,
        Extension:  ext,
        Hash:       hash, // 必填:SHA-256 hex
        Type:       "your_biz_type",
        AccessMode: &accessMode,
        Metadata: model.UploadMetadata{
            Extra: map[string]any{"source": "worker"},
        },
        Policy: upload.PolicyResolveExisting,
    })
    if err != nil {
        return model.Upload{}, err
    }
    return result.Upload, nil
}
Request 关键字段
字段说明
Hash必填,推荐 SHA-256 hex;用于秒传 / 镜像去重
Type业务分类(如 avatar、invoice、pixez_mirror),用于筛选与统计
AccessModenil 时按 type 默认:avatar → 公开(1),其余 → 私有(0)
SkipExtensionCheckWorker 场景若已自行校验扩展名,可设为 true
ObjectKeyFn可选自定义存储路径;默认 uploads/YYYY/MM/DD/{id}.{ext}
错误处理
错误含义Handler 映射建议
upload.ErrIngestStorageReadOnly存储迁移维护中response.AbortConflict
ingest.ErrForbidden无权删除他人文件HTTP 403
shared.ErrUnsupportedFormat扩展名不在白名单response.AbortBadRequest
删除
go
// 管理员 / 系统删除
_, err := upload.Remove(ctx, uploadID)

// 用户删除自己的文件
_, err := upload.RemoveOwned(ctx, userID, uploadID)
读取已存储对象(不上传)
go
uploadRec, err := repository.GetActiveUploadByID(ctx, uploadID)
obj, err := uploadstorage.OpenStoredObject(ctx, &uploadRec)
defer obj.Body.Close()

或通过门面(若已从 exports 暴露 OpenStoredObject)读取。HTTP 对外访问统一走 GET /f/:id。


后端:业务 API 引用已上传文件

推荐 两步流程(先上传、后提交业务):

  1. 前端 POST /api/v1/upload → 获得 upload.id
  2. 业务 API 接收 upload_id,用 repository.GetActiveUploadByID 校验存在且 status 为 active
  3. (可选)校验 upload.Type 是否为预期业务类型
  4. 将 upload_id 写入业务表字段(如 cover_file_id)

禁止在业务 Handler 中重复实现 multipart 解析,除非有极强的特殊协议需求。


前端:用户侧上传

使用 frontend/lib/services/upload/:

typescript
import { services } from '@/lib/services'
import { getFileUrl } from '@/lib/services/upload'

// 上传
const upload = await services.upload.uploadFile(file, 'invoice', { orderId: '123' })

// 展示
const url = getFileUrl(upload.id) // → /f/{id}

// Base64 图片(头像等)
const res = await services.upload.uploadBase64Image(croppedBase64, 'avatar', 'avatar.png')
前端规范
  • 新增上传相关 API 时,扩展 UploadService / AdminUploadService,在 frontend/lib/services/index.ts 注册
  • 图片预览使用 getFileUrl(id, quality?) 或 FileImagePreview 组件
  • 业务表单项只提交 upload_id,不要提交 blob URL 或 file_path

统计与排查

w_upload_stats 由 upload.Ingest / upload.Remove 自动维护,业务不得手动增量。

若发现 trend / total 与 w_uploads 不一致(常见于历史旁路写表):

go
upload.RebuildUploadStats(ctx) // 从 w_uploads 全量重建统计

排查清单:

  1. 业务是否绕过 upload.Ingest 直接 db.Create(&model.Upload{})?
  2. 是否手动调用已 Deprecated 的 ApplyUploadStatsAdd?
  3. 删除是否走 upload.Remove(须在软删前扣减统计)?

测试要求

后端 ingest 测试
  • 使用 testhelper.SetupTestEnvironment(t) 初始化 DB
  • 存储 mock:storage.MockStorage(...) + storage.IsEnabledFunc = func() bool { return true }
  • 禁止在源码目录硬编码 uploads/test 路径;本地文件测试用 t.TempDir() 或 mock backend
  • 覆盖:三种 Policy、Remove 后统计归零、ReadOnly 拒绝写入

参考:internal/apps/upload/ingest/ingest_test.go

Handler 回归

修改 upload handler 后运行:

bash
go test ./internal/apps/upload/...
make code-check

若变更 HTTP 接口,运行 make swagger。


存量代码迁移(旁路写表 → Ingest)

将以下模式:

go
storage.Active(ctx)
backend.Put(ctx, key, reader, size, mime)
db.DB(ctx).Create(&upload)

替换为:

go
upload.Ingest(ctx, upload.IngestRequest{ Policy: upload.PolicyResolveExisting, ... })

迁移完成后执行一次 upload.RebuildUploadStats(ctx) 修复历史统计偏差。


质量门禁 Checklist

完成文件上传相关开发后,确认:

  • 业务模块无 repository.CreateUpload / SoftDeleteUpload 调用
  • 业务模块无 storage.Active + Put 直接写文件
  • 业务表存 upload_id,不存 file_path
  • Worker 摄取使用正确的 Policy
  • 新增测试覆盖 ingest 路径
  • make code-check 通过
  • HTTP 变更已 make swagger

© Rain-kl, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/file-upload of Rain-kl/OpenFlare.

Open the folder on GitHubat commit 7c2304d

Compare with similar skills

File Upload next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

File Upload compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
File Upload this skillRain-kl/OpenFlare288—~1.7kAutomated safety check: PassApache-2.0
Cloudflare R2einverne/dotfiles121—~2.8kAutomated safety check: PassGPL-3.0
Cloudflare R2sickn33/agentic-awesome-skills47k2 repos~2.5kAutomated safety check: PassMIT
Cloudflare 3sundial-org/awesome-openclaw-skills663—~1.5kAutomated safety check: PassNone
Stripe Projectsfossasia/eventyay1.7k5 repos~2kAutomated safety check: NotesApache-2.0
Golivemikehasa/golive-skill1.2k—~13kAutomated safety check: NotesMIT

Similar skills

  • Cloudflare R2

    einverne/dotfiles

    Guide for implementing Cloudflare R2 - S3-compatible object storage with zero egress fees.

    121 GitHub stars~2.8k tokensUpdated 1 mo ago
    Backend & APIsAuto-check passed
  • Cloudflare R2

    sickn33/agentic-awesome-skills

    Manage Cloudflare R2 buckets, lifecycle, and signed URLs. An agent skill from sickn33/agentic-awesome-skills.

    47k GitHub starsUsed in 2 repos~2.5k tokens
    Backend & APIsAuto-check passed
  • Cloudflare 3

    sundial-org/awesome-openclaw-skills

    Manage Cloudflare Workers, KV, D1, R2, and secrets using the Wrangler CLI.

    663 GitHub stars~1.5k tokensUpdated 7 mo ago
    DevOps & CloudAuto-check passed
  • Stripe Projects

    fossasia/eventyay

    A skill your agent uses when the user wants to provision infrastructure or third-party services using Stripe Projects.

    1.7k GitHub starsUsed in 5 repos~2k tokens
    Backend & APIsAuto-check: notes
  • Golive

    mikehasa/golive-skill

    Take an agent-written app from repo to live production on the user's OWN accounts, with providers they choose (hosting, database, auth, payments, email, domain/DNS).

    1.2k GitHub stars~13k tokensUpdated 5 days ago
    Backend & APIsAuto-check: notes
  • Foundatio

    FoundatioFx/Foundatio

    A skill your agent uses when working with Foundatio infrastructure abstractions for .NET -- caching, queuing, messaging, file storage, distributed locking, or background jobs.

    2.1k GitHub stars~3.9k tokensUpdated yesterday
    Backend & APIsAuto-check passed

More from Rain-kl/OpenFlare

All 12 skills in this repo
  • Code Review Skill

    Rain-kl/OpenFlare

    Provides comprehensive code review guidance for React 19, Vue 3, Angular 17+, Svelte 5, Rust, TypeScript, Java, PHP, Python, Django, Go, C/.NET, Kotlin, Swift, NestJS, C/C++, and more.

    288 GitHub stars~2.3k tokensUpdated yesterday
    Auto-check: notes
  • Go Logging

    Rain-kl/OpenFlare

    在选择日志方案、配置 slog、编写结构化日志语句或决定日志级别时使用。也适用于设置生产日志、为日志添加请求作用域上下文或从 log 迁移到 slog 的场景,即使用户未明确提及日志。不涵盖错误处理策略(参见 go-error-handling)。

    288 GitHub stars~1.1k tokensUpdated yesterday
    Auto-check passed
  • New API

    Rain-kl/OpenFlare

    Wavelet 项目专用:当新增或修改自定义业务 API、新增业务路由、新增 service 层核心逻辑时必须使用。本技能指导包职责划分、推荐文件结构、路由解耦、Swagger 文档生成与质量门禁验证。

    288 GitHub stars~1.4k tokensUpdated yesterday
    Auto-check passed
  • Cache Framework

    Rain-kl/OpenFlare

    Wavelet 项目专用:当新增或修改业务缓存(RAM/Redis/DB 三层读路径)、缓存失效、多节点 pub/sub 同步、或评估高频读是否应接入缓存时必须使用。本技能说明系统标准缓存框架、参考实现、禁止写法与分布式一致性要求。

    288 GitHub stars~1.7k tokensUpdated yesterday
    Auto-check passed
  • Clickhouse Batchwriter

    Rain-kl/OpenFlare

    Wavelet 项目专用:当新增或修改 ClickHouse 批量写入、接入 internal/infra/persistence/batchwriter、将业务域异步 flush 到分析表、迁移 riskcontrol/节点访问日志/可观测时序写入、或评估 asyncinsert 与背压策略时必须使用。本技能指导分层职责、各域独立 Writer 实例、repository 批量 API…

    288 GitHub stars~1.4k tokensUpdated yesterday
    Auto-check passed
  • Database Migration

    Rain-kl/OpenFlare

    Wavelet 项目专用:当新增或修改数据库表结构、索引、初始化数据、系统配置 seed、模板 seed、默认管理员、goose SQL 迁移、internal/infra/persistence/migrator、ClickHouse 分析库 DDL 或数据库升级流程时必须使用。本技能指导在 internal/infra/persistence/migrator/goose 下编写…

    288 GitHub stars~1.3k tokensUpdated yesterday
    Auto-check passed

Works with

Categories

Questions about File Upload

What does File Upload do?

Wavelet 项目专用:当业务需要上传文件、读取已上传文件、在 Worker/任务中程序化摄取字节流、选择存储引擎能力、或排查 wuploads / 文件统计异常时必须使用。本技能指导 storage 与 upload 分层、upload.Ingest 策略选型、前后端接入与禁止旁路写表。. File Upload is an agent skill from Rain-kl/OpenFlare.

When should I use File Upload?

File Upload fits situations like: tasks that involve File uploads and storage.

How do I install File Upload in Claude Code?

Run `npx skills add Rain-kl/OpenFlare --skill file-upload -a claude-code`. Or copy the skill folder (.agents/skills/file-upload in Rain-kl/OpenFlare) into .claude/skills/file-upload in your project. Claude Code loads it when a task matches its description.

How do I install File Upload in Codex?

Run `npx skills add Rain-kl/OpenFlare --skill file-upload -a codex`. Or copy the skill folder (.agents/skills/file-upload in Rain-kl/OpenFlare) into .agents/skills/file-upload in your project. Codex loads it when a task matches its description.

Can I use File Upload in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Rain-kl/OpenFlare --skill file-upload -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/file-upload, .gemini/skills/file-upload, .github/skills/file-upload and .opencode/skills/file-upload in your project.

What does File Upload need to run?

Going by SKILL.md and its folder, File Upload needs the command-line tools its instructions call (make and go).

Does File Upload access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is File Upload safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does File Upload use?

File Upload is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does File Upload use?

About 1.7k tokens (SKILL.md is roughly 6.7k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to File Upload?

Skills that share tags, products or a category with File Upload: Cloudflare R2 (einverne/dotfiles, 121 stars), Cloudflare R2 (sickn33/agentic-awesome-skills, 47k stars), Cloudflare 3 (sundial-org/awesome-openclaw-skills, 663 stars) and Stripe Projects (fossasia/eventyay, 1.7k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains File Upload?

Rain-kl (a GitHub user) maintains it in Rain-kl/OpenFlare, which has 288 GitHub stars. The repository holds 12 skills in this directory. The repository was last updated on October 8, 2026.

Source: Rain-kl/OpenFlare on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.