Lagring av utvidelsesfiler
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 utvidelsesfiler lar en aktivert utvidelse laste opp bildefiler som tilhører en låst utvidelsesøkt.
Bruk den når JSON-utvidelsestilstand ikke er nok, for eksempel:
- puslespillbilder
- genererte forhåndsvisninger
- utfordringsbilder
- utvidelsesspesifikke medier som bør ryddes opp med låsen/økten
Denne lagringen er separat fra state.*. Bruk state.* for små JSON-data. Bruk fillagring kun for binære medier.
Forhold til tilstandsendepunkter
Utvidelsesstatusen er for JSON med liten øktomfang. Fra en iframe, bruk bridge read-kommandoen i stedet for å kalle REST direkte:
state.get
Den brokommandoen ruter til:
GET /api/extensions/sessions/:sessionId/state
Direkte backend-kall for å skrive tilstand bruker API-autentiseringsmodellen for installert utvidelse:
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH
Ikke send utvikler-API-nøkler til iframe-/nettleserkode.
Bruk backend-skrevet tilstand for varige referanser og brukergrensesnittdata, for eksempel:
{
"puzzleImageFileId": "file_record_id",
"selectedImageIds": ["file_record_id"],
"lastOpenedTab": "images"
}
Ikke lagre binære data, base64-bilder, nettleserens blob:-URL-er eller langlivede kopier av signedUrl i tilstanden. Signerte URL-er utløper og bør oppdateres med files.get når bildet gjengis. Tilstandsskrivinger er størrelsesbegrenset av utvidelsesappens stateMaxBytes-innstilling, som standard er 64 KiB.
Lagringsmodell
Chastify lagrer utvidelsesfiler i Chastify-administrert R2-lagring.
Hver opplastede fil spores med:
scope: "extension"appIdsessionIdoglockIdfor kjøretids-/øktfilertemplateIdfor filer som er gjort krav på av en lagret låsemalstaged,draftIdogexpiresAtfor oppsettopplastinger som ikke er gjort krav på ennåextensionKeypurpose
Adminport og 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.
Konfigurer oppstartsendepunkter
Bruk oppsettstaging bare når et oppsettgrensesnitt kjører før en utvidelsesøkt finnes.
Dette er en midlertidig opplastingsflyt. Den finnes for oppsett-/konfigurasjonsskjermer der brukeren kan laste opp en fil, deretter lukke modalvinduet eller deaktivere utvidelsen før en lås/økt opprettes. En trinnvis fil er ikke holdbar før den er gjort krav på ved å lagre utvidelseskonfigurasjonen som refererer til den.
Oppsettgrensesnitt kan sjekke tilgjengelighet og gjeldende trinnvis bruk før opplastingskontroller gjengis:
GET /api/extensions/apps/:appId/files/capabilities
Svaret inkluderer stagedQuota for den nåværende brukerens utløpte, trinnvise filer på den utvidelsesappen:
{
"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
Skjemafelt:
file: nødvendig bildefilpurpose: valgfri kort identifikator somjigsaw-config-imagedraftId: valgfri utkast-ID for oppsett; bruk samme verdi på nytt mens én oppsettmodal er åpen
Svaret inneholder en stabil file.id og en kortvarig signert URL for umiddelbar forhåndsvisning.
Eksempel på svar:
{
"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
}
}
For å gjenopprette oppsettopplastinger etter en sideoppdatering, oppgi trinnvise filer for gjeldende bruker og utvidelsesapp:
GET /api/extensions/apps/:appId/files/staged?purpose=jigsaw-config-image
Valgfrie spørreparametere:
purpose: returner kun trinnvise filer for ett brukstilfelle for oppsettdraftId: returner kun filer fra et kjent oppsettutkast
Hvis draftId utelates, returnerer Chastify den gjeldende brukerens ikke-utløpte, trinnvise filer for den appen. Dette er bevisst for oppsettsgrensesnitt: en bruker kan laste opp filer, laste inn siden på nytt eller bytte enhet, og oppsettskjermen kan gjenopprette disse midlertidige opplastingene før låsen/malen lagres.
Svaret på den trinnvise listen inkluderer også stagedQuota, som rapporterer den nåværende brukerens uutløpte trinnvise bruk for den appen:
{
"items": [],
"stagedQuota": {
"bytesUsed": 123456,
"fileCount": 1,
"maxBytes": 10485760,
"remainingBytes": 10362304
}
}
Oppsettgrensesnitt kan også oppdatere eller slette én trinnvis fil:
GET /api/extensions/apps/:appId/files/:fileId
DELETE /api/extensions/apps/:appId/files/staged/:fileId
Gjør krav på iscenesatte filer senere
Det finnes ikke noe separat «krav»-endepunkt på nettlesersiden. En mellomlagde fil kreves automatisk når Chastify lagrer en lås- eller malutvidelseskonfigurasjon som refererer til den mellomlagde filen.
Disse rutene krever mellomlagde filer etter at lås-/maldokumentet har en ID, og lagrer deretter utvidelseskonfigurasjonen på nytt med de påståtte filreferansene. Hvis kravet mislykkes, rulles den nyopprettede låsen/malen tilbake, slik at mellomlagde filer ikke blir stående knyttet til en ødelagt konfigurasjon.
Merknad om delt mal: Godkjente delte låser beholder kildemal-ID-en på den klonede aktive låsen. Malkrevde filer beholdes derfor mens eventuelle klonede låser fortsatt refererer til den malen. Hvis kildemalen slettes, forsinker Chastify slettingen av utvidelsesfilene til den siste klonede låsen som refererer til den slettede malen er slettet eller arkivert.
For å gjøre en trinnvis fil mulig å kreve, lagre en referanse som denne i utvidelseskonfigurasjonen som sendes inn av oppsettgrensesnittet:
{
"storageDraftId": "draft_123",
"images": [
{
"id": "file_record_id",
"provider": "chastify_storage",
"fileId": "file_record_id",
"url": "extension-file:file_record_id",
"title": "Puzzle image"
}
]
}
Ved lagring skanner Chastify konfigurasjonen for provider: "chastify_storage"-poster med en gyldig fileId, og gjør deretter følgende:
- bekrefter at filen tilhører gjeldende bruker og utvidelsesappen
- avviser utløpte, trinnvise filer
- avviser filer som allerede er gjort krav på av en annen lås-/malkontekst
- markerer refererte iscenesatte filer som hevdet
- binder filer som kreves til den lagrede låsen eller malen
- fjerner midlertidige felt
signedUrl,publicUrlogurlExpiresAtfør konfigurasjonen lagres - sletter urefererte, trinnvise filer fra samme
storageDraftId
Forlatte, trinnvise filer som aldri lagres, slettes ved opprydding etter utløpsdatoen.
Slik oppdaterer du en forhåndsvisning av oppsettet for en fil-ID som eies av gjeldende bruker og utvidelsesapp:
GET /api/extensions/apps/:appId/files/:fileId
Øktens sluttpunkter
Disse endepunktene krever vanlig autorisasjon og omfang for utvidelsesøkter.
Basissti:
/api/extensions/sessions/:sessionId/files
Evner
Sjekk dette før du gjengir opplastingskontroller.
GET /api/extensions/sessions/:sessionId/files/capabilities
Krever locks:read.
Eksempel på svar:
{
"enabled": true,
"provider": "r2",
"r2Configured": true,
"settings": {
"enabled": true,
"maxFileBytes": 10485760,
"maxBytesPerApp": 524288000,
"maxBytesPerSession": 52428800,
"maxStagedBytesPerUserPerApp": 10485760,
"allowedMimePrefixes": ["image/"]
}
}
Liste over filer
GET /api/extensions/sessions/:sessionId/files
Krever locks:read.
Eksempel på svar:
{
"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"
}
]
}
Få én fil
Bruk dette når utvidelsen din allerede har en lagret fil-ID og bare trenger en ny signert R2-lenke.
GET /api/extensions/sessions/:sessionId/files/:fileId
Krever locks:read.
Filen må tilhøre samme utvidelsesapp, økt og lås.
Eksempel på svar:
{
"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"
}
}
Last opp fil
POST /api/extensions/sessions/:sessionId/files
Content-Type: multipart/form-data
Krever locks:write.
Skjemafelt:
file: nødvendig bildefilpurpose: valgfri kort identifikator sompuzzle-imageellerpreview
Eksempel:
curl "https://chastify.net/api/extensions/sessions/SESSION_ID/files" \
-X POST \
-F "purpose=puzzle-image" \
-F "[email protected]"
Eksempel på svar:
{
"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"
}
}
Vanlige opplastingsfeil:
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
Slett fil
DELETE /api/extensions/sessions/:sessionId/files/:fileId
Krever locks:write.
Filen må tilhøre samme utvidelsesapp, økt og lås.
Iframe Bridge-handlinger
Iframe-utvidelser kan bruke den overordnede webbroen for lesing av kjøretidsfiler. Opplasting og sletting av kjøretidsfiler er øktmutasjoner og bør utføres av backend-en din med en app-scoped Developer API-nøkkel pluss 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øttede brohandlinger:
files.capabilities-> sjekk om fillagring er aktivert og hvilke kvoter som gjelderfiles.list-> liste filer som eies av gjeldende utvidelsesøktfiles.get-> oppdater én signert R2-URL fra en lagret fil-ID
Oppsett av iframes kan bruke flere bronavn før en kjøretidssesjon eksisterer. I oppsettmodus oppretter files.upload mellomlagde filer, files.list/files.staged.list viser uutløpte mellomlagde filer for gjeldende bruker og app, og files.delete sletter en mellomlagd fil. Oppsettskonteksten init inkluderer storageDraftId. Inkluder denne verdien i den lagrede konfigurasjonen som storageDraftId hvis du vil at Chastify skal rense urefererte filer fra samme utkast umiddelbart ved lagring.
Oppsettet files.upload godtar også dataUrl for enkle iframe-klienter:
await bridge.request("files.upload", {
dataUrl: canvas.toDataURL("image/webp", 0.9),
filename: "preview.webp",
purpose: "preview"
}, 60000);
Foretrekk opplastinger av File eller Blob når det er mulig. Bruk dataUrl kun for små genererte bilder fordi base64-nyttelaster er større i minnet.
Signerte lenker
Den stabile filidentifikatoren er id.
Bruk signedUrl for å vise eller laste ned filen. Signerte lenker er kortvarige R2 GetObject-URL-er generert av Chastify. publicUrl beholdes som et kompatibilitetsalias og inneholder for øyeblikket den samme signerte URL-en.
Når en signert lenke utløper, ring GET /api/extensions/sessions/:sessionId/files/:fileId for å motta en ny lenke for én lagret fil, eller GET /api/extensions/sessions/:sessionId/files for å oppdatere alle lenker til øktfiler.
Oppryddingens livssyklus
Utvidelsesfiler ryddes opp via en BullMQ-støttet oppryddingskø.
Opprydding er planlagt når:
- en utvidelsesapp er slettet
- Lås-/øktutvidelsesdokumenter slettes under fjerning av lås/arkivopprydding
- en fil slettes eksplisitt via sesjonsfilens endepunkt
Køen holder kostbar R2-sletting og databaseopprydding unna forespørselsbanen. Hvis køopprydding mislykkes, går serveren tilbake til opprydding i prosessen etter svaret der en forespørselskontekst finnes, eller direkte beste-innsats-opprydding i livssyklusopprydding på lavere nivå.
Ytelsesnotater
- Funksjonskontroller bør utføres før opplastingsgrensesnittet vises.
- Opplastinger er begrenset av grenser per fil, per økt og per app.
- Kvotekontroller bruker indekserte
UserFile-metadata forscope + appId,scope + sessionIdogscope + lockId. - Rydde opp strømmer som samsvarer med filoppføringer i stedet for å laste alle URL-er inn i minnet.
- Opplastede rasterbilder behandles og lagres som optimaliserte webbilder.
Sikkerhetsnotater
- Ikke bruk URL-adresser for bilde fra utvidelser som bevis på at de er fullført.
- Lagre kun Chastify-utstedte filposter som klarerte filutvidelser.
- Bind filoppføringer til
appId,sessionIdoglockId. - Håndhev
locks:writefor opplastinger og slettinger. - Valider MIME-typen og avvis SVG.
- Hold administratorkontrollerte kvoter aktivert før du tillater bred offentlig bruk.
- Bruk validering på serversiden for alle arbeidsflyter som er avhengige av opplastede filer.
Direkteruter vs. bro
Bruk iframe-broen når utvidelsen din kjører inne i Chastify. Den beholder Chastify-autentisering på den overordnede siden og unngår at rutedetaljer eksponeres for iframe-en.
Bruk direkte øktruter kun fra førsteparts Chastify-grensesnitt eller klarerte backend-flyter som allerede har gyldig autorisasjon for utvidelsesøkt.