File Upload Gallery
Upload images with metadata, serve them back, and auto-clean storage on delete.
Config
typescript
{
name: 'images',
autoSetUid: true,
r2Base: 'gallery', // R2 bucket prefix for this table
autoDeleteR2Files: true, // delete files from R2 when record is deleted
fields: [
...baseFields,
{ name: 'owner_id', type: 'relation', sqlType: 'text', notNull: true,
foreignKey: { table: 'users', column: 'id', onDelete: 'CASCADE' } },
{ name: 'title', type: 'text', sqlType: 'text', notNull: true },
{ name: 'file', type: 'file', sqlType: 'text', notNull: true },
{ name: 'thumb', type: 'file', sqlType: 'text' },
{ name: 'caption', type: 'text', sqlType: 'text' },
],
triggers: [createdTrigger, updatedTrigger],
indexes: [{ fields: 'owner_id' }],
extensions: [{
name: 'rules',
listRule: 'true',
viewRule: 'true',
createRule: 'auth.uid != null & owner_id == auth.uid',
updateRule: 'auth.uid == owner_id',
deleteRule: 'auth.uid == owner_id',
} as TableRulesExtensionData],
}Upload a file
Files are uploaded via multipart/form-data. Use @filePayload for the actual file and @jsonPayload for the record data.
bash
curl -X POST http://localhost:8787/api/v1/table/images/insert \
-H 'Authorization: Bearer <token>' \
-F '@jsonPayload={"values":{"owner_id":"USER_ID","title":"Sunset"}};type=application/json' \
-F '@filePayload[file]=@/path/to/sunset.jpg'Download a file
GET http://localhost:8787/api/v1/files/<table>/<record_id>/<field_name>/<file_name>Example:
http://localhost:8787/api/v1/files/images/abc123/file/sunset.jpgDelete (auto-cleans R2)
bash
curl -X POST http://localhost:8787/api/v1/table/images/delete \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{"where": "id = \"abc123\""}'With autoDeleteR2Files: true, the actual file in R2 is deleted when the record is deleted. No orphaned files.