PocketBase 做一个本地低代码后台手机表单和文件上传跑通后用 cpolar 给产品临时验收有些 Demo 不值得起一套 Spring Boot Vue也不想为了一个临时表单去申请 SaaS。我的做法更粗暴PocketBase 单文件启动本机把 collection、字段、上传和权限跑通再用 cpolar 给产品一个临时 HTTPS 地址让他直接拿手机验收。这篇只做一件事把 PocketBase 当成一个本地低代码后台跑通新增、查询、文件上传和基础权限。验收结束就关隧道不把本机长期挂到公网。这类场景PocketBase 很合适PocketBase 本质上是一个单文件后端自带 SQLite、Admin UI、Auth、Collection、REST API、文件存储。它不像 NocoDB 那样主打表格协作也不是 Appsmith 那种内部工具面板更不是 Directus CMS。我最喜欢它的一点是本地原型特别快。比如要给产品验收一个“线索收集表”字段里有姓名、手机号、备注、附件截图。正常写后端要建项目、连库、写接口、处理上传、配权限PocketBase 里点几个字段接口和上传就出来了。这篇用 macOS/Linux 命令演示Windows 也一样下载对应压缩包后执行pocketbase.exe serve即可。端口使用 PocketBase 默认的8090cpolar 只转发这个端口。下载并启动 PocketBase先新建一个演示目录避免把它和别的项目混在一起mkdir -p ~/demo/pb-feedback cd ~/demo/pb-feedback到 PocketBase 官网下载对应系统的 release 包。macOS Apple Silicon 可以用类似下面的方式版本号按官网最新稳定版替换curl -L -o pocketbase.zip \ https://github.com/pocketbase/pocketbase/releases/download/v0.23.12/pocketbase_0.23.12_darwin_arm64.zip unzip pocketbase.zip chmod x pocketbaseLinux x64 可以换成curl -L -o pocketbase.zip \ https://github.com/pocketbase/pocketbase/releases/download/v0.23.12/pocketbase_0.23.12_linux_amd64.zip unzip pocketbase.zip chmod x pocketbase启动服务./pocketbase serve --http127.0.0.1:8090我这里故意绑定127.0.0.1意思是只允许本机访问。后面要给外部手机验收也通过 cpolar 转发这个本地端口而不是让 PocketBase 直接监听0.0.0.0。启动后终端会看到类似地址Server started at http://127.0.0.1:8090 REST API: http://127.0.0.1:8090/api/ Admin UI: http://127.0.0.1:8090/_/浏览器打开http://127.0.0.1:8090/_/第一次进入会要求创建 Admin。这里用一个只给本次演示使用的邮箱和强密码别用生产密码也别把密码写进聊天群。建一个 feedback collection进入 Admin 后左侧选择 Collections新建一个feedbackcollection。类型选 Base collection 就够了它适合公开表单、匿名反馈、测试数据这类场景。字段我建议这样建字段名类型说明nameText提交人姓名设为必填phoneText手机号或测试联系方式演示环境用假数据messageText反馈内容设为必填attachmentFile上传截图或附件允许 1 个文件statusSelect状态选项为 new、reviewed默认 newattachment字段可以限制文件类型比如只允许image/png,image/jpeg,application/pdf文件大小也建议限制一下例如 5MB。Demo 阶段别让别人随手传几十 MB 的视频把本机磁盘打满。status字段用于后续内部处理不建议让手机表单提交时随便改。我们可以在前端不传它PocketBase 使用默认值new。配基础权限别一上来全放开PocketBase 每个 collection 都有 API Rules。为了让产品手机端能匿名新增和查询演示数据可以先配成下面这样规则配置List/Search rule空字符串View rule空字符串Create rule空字符串Update rulerequest.auth.id ! Delete rulerequest.auth.id ! 这里的“空字符串”不是随便写一个空格而是规则输入框留空。它表示允许公开访问该动作。这样配置后未登录用户可以新增、列表查询、查看详情但不能更新和删除。对临时验收来说这个边界比较清楚产品能在手机上提交、刷新看到结果但不会误删数据。如果你的验收数据不允许公开查询那就把 List/View 也改成需要登录或者单独建一个测试账号。本文为了让手机验收链路最短采用公开读写新增的 Demo 配置但只放测试数据。血泪教训不要为了省事把所有规则都留空。Create 可以开放Update/Delete 不要开放。否则别人拿到地址后可以直接改掉或删掉你的测试记录。用 REST API 先跑通新增在做 H5 页面前先用 curl 验证 API。新增一条不带文件的数据curl -X POST http://127.0.0.1:8090/api/collections/feedback/records \ -H Content-Type: application/json \ -d { name: 测试用户A, phone: 13800000000, message: 手机端表单基础字段验收, status: new }返回里会有id、created、updated等字段。再查列表curl http://127.0.0.1:8090/api/collections/feedback/records?sort-created如果能看到刚才的数据collection 和基础权限就通了。再试一下文件上传。准备一张测试图比如test.png然后执行curl -X POST http://127.0.0.1:8090/api/collections/feedback/records \ -F name测试用户B \ -F phone13900000000 \ -F message带附件上传的反馈 \ -F statusnew \ -F attachment./test.pngPocketBase 的文件字段走multipart/form-data。上传成功后记录里会出现attachment文件名。文件访问路径一般是这种格式/api/files/feedback/{recordId}/{filename}在 Admin UI 里点开这条记录也能看到上传文件。这一步很关键别跳过。很多 Demo 现场翻车不是接口没通而是文件字段类型、大小限制或权限没提前测。写一个最小 H5 表单只用 API 验收不够产品一般还是希望拿手机点一下。所以我们写一个最小index.html直接放在本地目录里打开即可。新建文件cat index.html EOF !doctype html html langzh-CN head meta charsetutf-8 / meta nameviewport contentwidthdevice-width, initial-scale1 / titlePocketBase 手机反馈验收/title style body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; padding: 20px; max-width: 680px; margin: auto; } label { display: block; margin-top: 14px; font-weight: 600; } input, textarea, button { width: 100%; box-sizing: border-box; margin-top: 6px; padding: 10px; font-size: 16px; } textarea { min-height: 100px; } button { margin-top: 18px; border: 0; border-radius: 8px; background: #111827; color: white; } .item { border: 1px solid #ddd; border-radius: 8px; padding: 12px; margin-top: 12px; } .muted { color: #666; font-size: 13px; } /style /head body h2PocketBase 反馈表单验收/h2 form idform label姓名/label input namename required placeholder测试用户A / label手机号/label input namephone placeholder13800000000 / label反馈内容/label textarea namemessage required placeholder这里填写测试反馈/textarea label附件截图/label input nameattachment typefile acceptimage/png,image/jpeg,application/pdf / button typesubmit提交反馈/button /form h3最新提交/h3 div idlist classmuted加载中.../div script const PB_BASE location.origin.includes(8090) ? http://127.0.0.1:8090 : location.origin; async function loadList() { const res await fetch(${PB_BASE}/api/collections/feedback/records?sort-createdperPage10); const data await res.json(); const list document.querySelector(#list); list.innerHTML ; for (const row of data.items || []) { const fileUrl row.attachment ? ${PB_BASE}/api/files/feedback/${row.id}/${row.attachment} : ; const div document.createElement(div); div.className item; div.innerHTML strong${row.name || 匿名}/strong div${row.message || }/div div classmuted${row.phone || } ${row.created}/div ${fileUrl ? diva href${fileUrl} target_blank查看附件/a/div : } ; list.appendChild(div); } } document.querySelector(#form).addEventListener(submit, async (e) { e.preventDefault(); const fd new FormData(e.target); fd.append(status, new); const res await fetch(${PB_BASE}/api/collections/feedback/records, { method: POST, body: fd }); if (!res.ok) { alert(提交失败 await res.text()); return; } e.target.reset(); await loadList(); alert(提交成功); }); loadList(); /script /body /html EOF这里有个小设计如果页面是通过http://127.0.0.1:8090或 cpolar 入口访问就让 API 走同源地址。这样手机打开 cpolar 的 HTTPS 地址时请求也会打到同一个 PocketBase 服务不需要额外配置前端服务器。要让 PocketBase 托管这个 HTML可以把它放进pb_public目录mkdir -p pb_public mv index.html pb_public/index.htmlPocketBase 会把pb_public作为静态目录。现在本机打开http://127.0.0.1:8090/你应该能看到表单。提交一条带图片的数据再刷新列表能看到新增记录和附件链接。用 cpolar 开一个临时 HTTPS 入口本地链路通了再给产品或测试同事一个手机可访问地址。安装并登录 cpolar 后执行cpolar http 8090终端会输出一个 HTTPS 地址形如https://xxxx.cpolar.top把这个地址发给产品让他用手机浏览器打开https://xxxx.cpolar.top/验收清单建议直接写清楚别让对方自由发挥打开手机表单页面新增一条反馈上传一张截图或 PDF刷新后能看到最新记录点开附件可以预览或下载尝试修改/删除记录应该不允许Admin UI 只由开发本人本机使用不给外部人员账号。如果产品要看后台记录建议你共享屏幕或导出测试数据不要把 Admin 账号直接发出去。临时验收看的是链路不是把管理权限交出去。验收时最容易忽略的权限问题我建议你专门测一下 Update/Delete。PocketBase 的 REST API 路径很直白别人拿到记录 ID 后可以尝试请求curl -X PATCH http://127.0.0.1:8090/api/collections/feedback/records/RECORD_ID \ -H Content-Type: application/json \ -d {message:我试图修改这条记录}如果规则配置正确未登录请求会被拒绝。删除也是一样curl -X DELETE http://127.0.0.1:8090/api/collections/feedback/records/RECORD_ID这一步不是找麻烦而是防止“链接发出去之后测试数据被别人改掉”。Demo 可以简单但权限边界不能糊。如果你需要让产品登录后才能查看列表可以用 PocketBase 的 Auth collection 建一个测试用户再把 List/View rule 改成request.auth.id ! 对应前端再加登录接口。本文为了控制篇幅不展开完整登录页。真实项目里我更推荐把查询和管理动作收回到登录态下只把 Create 暂时开放。安全边界要提前说清楚这类本地临时验收最怕两件事一是把生产数据拿来演示二是把本机不该暴露的东西顺手暴露出去。我的底线是下面这些只使用测试数据不放真实手机号、客户资料、合同、身份证、内部截图cpolar 只转发8090这个 PocketBase Web/API 端口不暴露宿主机目录、SQLite 数据库文件、pb_data、服务器 shell不暴露 Admin 密码不把 Admin 账号发给外部验收人员不开放 MySQL、Redis、SSH、Docker 面板等其他开发端口验收结束马上关闭 cpolar 进程长期环境要改成正式鉴权、正式域名、HTTPS 证书、权限策略、备份和日志审计。PocketBase 的数据默认在当前目录的pb_data里。这个目录不要拿来做静态文件目录也不要通过其他文件服务暴露出去。SQLite 文件不是给别人下载的Admin 密码也不是验收材料。关闭临时入口很简单在运行 cpolar 的终端按Ctrl CPocketBase 也可以按Ctrl C停掉。验收结束后如果不再需要这批数据可以整个演示目录打包归档或删除。写在最后PocketBase 适合解决一种很具体的问题我现在就需要一个能新增、能查、能上传文件、能用 REST API 对接的小后端而且希望今天就给产品在手机上验收。它不是万能低代码平台也不应该被拿来绕过正式后端设计。但在原型、内测、表单、文件上传 Demo 这些场景里单文件启动、Admin UI 配 collection、REST API 直接可用确实很省时间。我的建议是本地开发大胆用临时验收短时开生产上线认真收口。只要边界守住PocketBase cpolar 这个组合会非常顺手。