Lagring av tilläggsfiler
TLDR: store the file id, render with a signed URL.
When an extension uploads a file, Chastify returns a stable id and a short-lived signedUrl. Store the id in your extension config, state, or own database.
When your extension page loads later, call bridge.request("files.get", { fileId }) or GET /api/extensions/sessions/:sessionId/files/:fileId with the stored id. Chastify verifies that the file belongs to the same extension app, session, and lock, then returns a fresh signed R2 URL.
Render the image with <img src={file.signedUrl} />. Do not store signed URLs long-term because they expire.
Lagring av tilläggsfiler låter ett aktiverat tillägg ladda upp bildfiler som tillhör en låst tilläggssession.
Använd den när JSON-tilläggsstatus inte är tillräckligt, till exempel:
- pusselbilder
- genererade förhandsvisningar
- utmaningsfoton
- tilläggsspecifik media som bör rensas med lås/session
Denna lagring är separat från state.*. Använd state.* för små JSON-data. Använd fillagring endast för binära medier.
Relation till tillståndsändpunkter
Tilläggets tillstånd är för JSON med liten sessionsomfattning. Använd kommandot bridge read från en iframe istället för att anropa REST direkt:
state.get
Den bryggkommandorutten till:
GET /api/extensions/sessions/:sessionId/state
Direkta backend-anrop för att skriva tillstånd använder autentiseringsmodellen för installerade extensions-API:er:
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH
Skicka inte utvecklar-API-nycklar till iframe/webbläsarkod.
Använd backend-skrivet tillstånd för varaktiga referenser och UI-data, till exempel:
{
"puzzleImageFileId": "file_record_id",
"selectedImageIds": ["file_record_id"],
"lastOpenedTab": "images"
}
Lagra inte binära data, base64-bilder, webbläsarens blob:-URL:er eller långlivade kopior av signedUrl i tillståndet. Signerade URL:er upphör att gälla och bör uppdateras med files.get när bilden renderas. Tillståndsskrivningar begränsas av tilläggsappens stateMaxBytes-inställning, som standard är 64 KiB.
Lagringsmodell
Chastify lagrar tilläggsfiler i Chastify-hanterad R2-lagring.
Varje uppladdad fil spåras med:
scope: "extension"appIdsessionIdochlockIdför runtime-/sessionsfilertemplateIdför filer som anspråk gjorts av en sparad låsmallstaged,draftIdochexpiresAtför installationsuppladdningar som ännu inte har gjorts anspråk påextensionKeypurpose
Admin Gate och kvoter
Admin controlled
Extension file storage is disabled by default.
Admins can enable it and configure:
- maximum bytes per file
- maximum total bytes per extension app
- maximum total bytes per active extension session
- maximum staged bytes per user and extension app
- allowed MIME prefixes
The first implementation is image-focused and should use image/* uploads. SVG is not accepted by the storage service.
If storage is disabled or R2 is not configured, upload requests fail before the server reads the multipart file body.
Staged setup uploads count toward the current user's per-app staged quota until they are claimed. Claimed files count toward the per-extension app quota. Runtime files with a session id also count toward the per-session quota.
Konfigurera mellanlagringsslutpunkter
Använd endast installationsintervall när ett installationsgränssnitt körs innan en tilläggssession finns.
Detta är ett tillfälligt uppladdningsflöde. Det finns för installations-/konfigurationsskärmar där användaren kan ladda upp en fil och sedan stänga modalfönstret eller inaktivera tillägget innan en låsning/session skapas. En mellanlagrad fil är inte hållbar förrän den antas genom att spara tilläggskonfigurationen som refererar till den.
Installationsgränssnitt kan kontrollera tillgänglighet och aktuell stegvis användning innan uppladdningskontroller renderas:
GET /api/extensions/apps/:appId/files/capabilities
Svaret inkluderar stagedQuota för den aktuella användarens oförfallna mellanlagrade filer i den tilläggsappen:
{
"enabled": true,
"provider": "r2",
"r2Configured": true,
"supportsStagedSetupFiles": true,
"stagedQuota": {
"bytesUsed": 123456,
"fileCount": 1,
"maxBytes": 10485760,
"remainingBytes": 10362304
}
}
POST /api/extensions/apps/:appId/files/stage
Content-Type: multipart/form-data
Formulärfält:
file: obligatorisk bildfilpurpose: valfri kort identifierare såsomjigsaw-config-imagedraftId: valfritt utkast-ID för installation; återanvänd samma värde medan en installationsmodal är öppen
Svaret innehåller en stabil file.id och en kortlivad signerad URL för omedelbar förhandsgranskning.
Exempelsvar:
{
"file": {
"id": "file_record_id",
"signedUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"publicUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"urlExpiresAt": "2026-05-28T12:10:00.000Z",
"sizeBytes": 123456,
"originalName": "puzzle.jpg",
"mimeType": "image/webp",
"purpose": "jigsaw-config-image",
"uploadedAt": "2026-05-28T12:00:00.000Z"
},
"stagedQuota": {
"bytesUsed": 123456,
"fileCount": 1,
"maxBytes": 10485760,
"remainingBytes": 10362304
}
}
För att återställa installationsuppladdningar efter en siduppdatering, lista mellanlagrade filer för den aktuella användaren och tilläggsappen:
GET /api/extensions/apps/:appId/files/staged?purpose=jigsaw-config-image
Valfria frågeparametrar:
purpose: returnera endast mellanlagrade filer för ett installationsfalldraftId: returnerar endast filer från ett känt installationsutkast
Om draftId utelämnas returnerar Chastify den aktuella användarens oförutsedda mellanlagrade filer för den appen. Detta är avsiktligt för installationsgränssnitt: en användare kan ladda upp filer, ladda om sidan eller byta enhet, och installationsskärmen kan återställa dessa tillfälliga uppladdningar innan låset/mallen sparas.
Svaret för den etappade listan inkluderar även stagedQuota, som rapporterar den aktuella användarens oförutsedda etappade användning för den appen:
{
"items": [],
"stagedQuota": {
"bytesUsed": 123456,
"fileCount": 1,
"maxBytes": 10485760,
"remainingBytes": 10362304
}
}
Installationsgränssnitten kan också uppdatera eller ta bort en mellanlagrad fil:
GET /api/extensions/apps/:appId/files/:fileId
DELETE /api/extensions/apps/:appId/files/staged/:fileId
Anspråk på mellanlagrade filer senare
Det finns ingen separat "anspråks"-slutpunkt på webbläsarsidan. En mellanlagrad fil anspråks automatiskt när Chastify sparar en lås- eller malltilläggskonfiguration som refererar till den mellanlagrade filen.
Dessa rutter gör anspråk på mellanlagrade filer efter att lås-/malldokumentet har ett ID, och sparar sedan tilläggskonfigurationen igen med de anspråkade filreferenserna. Om anspråket misslyckas återställs det nyskapade låset/mallen så att mellanlagrade filer inte lämnas kvar kopplade till en trasig konfiguration.
Obs om delad mall: accepterade delade lås behåller källmall-ID:t på det klonade aktiva låset. Mallanspråktagna filer behålls därför medan eventuella klonade lås fortfarande refererar till den mallen. Om källmallen tas bort, fördröjer Chastify borttagningen av dess tilläggsfiler tills det sista klonade låset som refererar till den borttagna mallen har tagits bort eller arkiverats.
För att göra en mellanlagrad fil anspråkbar, lagra en referens som denna i tilläggskonfigurationen som skickas av installationsgränssnittet:
{
"storageDraftId": "draft_123",
"images": [
{
"id": "file_record_id",
"provider": "chastify_storage",
"fileId": "file_record_id",
"url": "extension-file:file_record_id",
"title": "Puzzle image"
}
]
}
Vid sparning skannar Chastify konfigurationen efter provider: "chastify_storage"-poster med en giltig fileId och gör sedan följande:
- verifierar att filen tillhör den aktuella användaren och tilläggsappen
- avvisar utgångna, mellanlagrade filer
- avvisar filer som redan har gjorts anspråk på av en annan lås-/mallkontext
- markerar refererade mellanlagrade filer som anspråk
- binder anspråkgjorda filer till det sparade låset eller mallen
- tar bort de tillfälliga fälten
signedUrl,publicUrlochurlExpiresAtinnan konfigurationen sparas - tar bort orefererade mellanlagrade filer från samma
storageDraftId
Övergivna mellanlagrade filer som aldrig sparas raderas genom rensning efter att de har löpt ut.
Så här uppdaterar du en förhandsgranskning av installationen för ett fil-ID som ägs av den aktuella användaren och tilläggsappen:
GET /api/extensions/apps/:appId/files/:fileId
Sessionsslutpunkter
Dessa slutpunkter kräver normal auktorisering och omfång för tilläggssessioner.
Basväg:
/api/extensions/sessions/:sessionId/files
Förmågor
Kontrollera detta innan du renderar uppladdningskontroller.
GET /api/extensions/sessions/:sessionId/files/capabilities
Kräver locks:read.
Exempelsvar:
{
"enabled": true,
"provider": "r2",
"r2Configured": true,
"settings": {
"enabled": true,
"maxFileBytes": 10485760,
"maxBytesPerApp": 524288000,
"maxBytesPerSession": 52428800,
"maxStagedBytesPerUserPerApp": 10485760,
"allowedMimePrefixes": ["image/"]
}
}
Lista filer
GET /api/extensions/sessions/:sessionId/files
Kräver locks:read.
Exempelsvar:
{
"items": [
{
"id": "file_record_id",
"signedUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"publicUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"urlExpiresAt": "2026-05-28T12:10:00.000Z",
"sizeBytes": 123456,
"originalName": "puzzle.jpg",
"mimeType": "image/webp",
"purpose": "puzzle-image",
"uploadedAt": "2026-05-28T12:00:00.000Z"
}
]
}
Hämta en fil
Använd detta när ditt tillägg redan har ett lagrat fil-ID och bara behöver en ny signerad R2-länk.
GET /api/extensions/sessions/:sessionId/files/:fileId
Kräver locks:read.
Filen måste tillhöra samma tilläggsapp, session och lås.
Exempelsvar:
{
"file": {
"id": "file_record_id",
"signedUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"publicUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"urlExpiresAt": "2026-05-28T12:10:00.000Z",
"sizeBytes": 123456,
"originalName": "puzzle.jpg",
"mimeType": "image/webp",
"purpose": "puzzle-image",
"uploadedAt": "2026-05-28T12:00:00.000Z"
}
}
Ladda upp fil
POST /api/extensions/sessions/:sessionId/files
Content-Type: multipart/form-data
Kräver locks:write.
Formulärfält:
file: obligatorisk bildfilpurpose: valfri kort identifierare såsompuzzle-imageellerpreview
Exempel:
curl "https://chastify.net/api/extensions/sessions/SESSION_ID/files" \
-X POST \
-F "purpose=puzzle-image" \
-F "[email protected]"
Exempelsvar:
{
"file": {
"id": "file_record_id",
"signedUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"publicUrl": "https://chastify.<account-id>.r2.cloudflarestorage.com/extensions/abc.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Signature=...",
"urlExpiresAt": "2026-05-28T12:10:00.000Z",
"sizeBytes": 123456,
"originalName": "puzzle.jpg",
"mimeType": "image/webp",
"purpose": "puzzle-image",
"uploadedAt": "2026-05-28T12:00:00.000Z"
}
}
Vanliga uppladdningsfel:
extension_file_storage_disabledextension_file_storage_requires_r2file_too_largeinvalid_file_typeextension_app_storage_quota_exceededextension_session_storage_quota_exceededextension_staged_user_app_storage_quota_exceeded
Ta bort fil
DELETE /api/extensions/sessions/:sessionId/files/:fileId
Kräver locks:write.
Filen måste tillhöra samma tilläggsapp, session och lås.
Iframe-bryggåtgärder
Iframe-tillägg kan använda den överordnade webbbryggan för läsning av runtime-filer. Uppladdning och borttagning av runtime-filer är sessionsmutationer och bör utföras av din backend med en app-scope Developer API-nyckel plus x-chastify-main-token.
const capabilities = await bridge.request("files.capabilities", {});
const refreshed = await bridge.request("files.get", {
fileId: "file_record_id"
});
image.src = refreshed.file.signedUrl;
Stödda bryggåtgärder:
files.capabilities-> kontrollera om fillagring är aktiverad och vilka kvoter som gällerfiles.list-> lista filer som ägs av den aktuella tilläggssessionenfiles.get-> uppdatera en signerad R2-URL från ett lagrat fil-ID
Installations-iframes kan använda ytterligare bryggnamn innan en runtime-session existerar. I installationsläge skapar files.upload mellanlagrade filer, files.list/files.staged.list listar outgångna mellanlagrade filer för den aktuella användaren och appen, och files.delete tar bort en mellanlagrad fil. Installations-init-kontexten inkluderar storageDraftId; inkludera det värdet i din sparade konfiguration som storageDraftId om du vill att Chastify ska rensa orefererade filer från samma utkast omedelbart när det sparas.
Installationsprogrammet files.upload accepterar även dataUrl för enkla iframe-klienter:
await bridge.request("files.upload", {
dataUrl: canvas.toDataURL("image/webp", 0.9),
filename: "preview.webp",
purpose: "preview"
}, 60000);
Föredra uppladdningar av File eller Blob när det är möjligt. Använd endast dataUrl för små genererade bilder eftersom base64-nyttolaster är större i minnet.
Signerade länkar
Den stabila filidentifieraren är id.
Använd signedUrl för att visa eller ladda ner filen. Signerade länkar är kortlivade R2 GetObject-URL:er som genereras av Chastify. publicUrl behålls som ett kompatibilitetsalias och innehåller för närvarande samma signerade URL.
När en signerad länk upphör att gälla, anropa GET /api/extensions/sessions/:sessionId/files/:fileId för att få en ny länk för en lagrad fil, eller GET /api/extensions/sessions/:sessionId/files för att uppdatera alla sessionsfilslänkar.
Rengöringslivscykel
Tilläggsfiler rensas via en BullMQ-baserad rensningskö.
Städning är planerad när:
- en tilläggsapp har raderats
- Lås-/sessionstilläggsdokument raderas under borttagning av lås/arkivrensning
- en fil tas uttryckligen bort via sessionsfilens slutpunkt
Kön håller dyr R2-borttagning och databasrensning borta från sökvägen för begäran. Om köuppkopplingen misslyckas återgår servern till rensning under processen efter svaret där en begärankontext finns, eller direkt rensning med bästa möjliga insats i livscykelrensning på lägre nivå.
Prestandanteckningar
- Funktionskontroller bör utföras innan uppladdningsgränssnittet visas.
- Uppladdningar begränsas av gränser per fil, per session och per app.
- Kvotkontroller använder indexerade
UserFile-metadata förscope + appId,scope + sessionIdochscope + lockId. - Rensa strömmar som matchar filposter istället för att läsa in alla URL:er i minnet.
- Uppladdade rasterbilder bearbetas och lagras som optimerade webbbilder.
Säkerhetsanmärkningar
- Behandla inte bild-URL:er från tillägg som pålitliga bevis på slutförande.
- Lagra endast Chastify-utfärdade filposter som betrodda tilläggsfiler.
- Bind filposter till
appId,sessionIdochlockId. - Tillämpa
locks:writeför uppladdningar och borttagningar. - Validera MIME-typen och avvisa SVG.
- Håll administratörsstyrda kvoter aktiverade innan du tillåter bred offentlig användning.
- Använd serversidesvalidering för alla arbetsflöden som är beroende av uppladdade filer.
Direkta rutter kontra bro
Använd iframe-bryggan när ditt tillägg körs inuti Chastify. Det behåller Chastify-autentiseringen på den överordnade sidan och undviker att ruttinformation exponeras för iframen.
Använd endast direkta sessionsrutter från förstaparts Chastify-gränssnitt eller betrodda backend-flöden som redan har giltig auktorisering för tilläggssession.