Appwrite Plugins Storage
Appwrite Plugins

Storage

Upload, view, and download files from Appwrite storage buckets.


Appwrite Configuration

In your Appwrite project's Storage dashboard, create a bucket.

Within a bucket you can see its files and configure settings like allowed file types, maximum file size, encryption, and antivirus scanning.


Register Storage Buckets

Register storage buckets in your manifest.json under the data property, same as local data files and database tables. Include the appwriteBucketId value provided by Appwrite.

manifest.json
{
    "data": {
        "assets": {
            "appwriteBucketId": "your-bucket-id"
        }
    },
    "appwrite": {
        "projectId": "your-project-id",
        "endpoint": "your-API-endpoint"
    }
}

In this example, the "assets" data source name is arbitrary, used to later reference bucket content in the frontend. An Appwrite data source will automatically reference the appwrite property for credentials.

Alternatively, credentials can be added directly to a data source:

manifest.json
{
    "data": {
        "assets": {
            "projectId": "your-project-id",
            "endpoint": "your-API-endpoint",
            "appwriteBucketId": "your-bucket-id"
        }
    }
}

Scope

Scoping automatically filters file access by user or team, ensuring users only see files they're permitted to access. Configure scope in manifest.json:

manifest.json
{
    "data": {
        "assets": {
            "appwriteBucketId": "your-bucket-id",
            "scope": "user"
        }
    }
}

Scope options are:

Scope Description Permission Used
"user" Single user's files User permissions
"team" Current team's files Team permissions
"teams" All teams user belongs to Team permissions
["user", "team"] User's files OR current team's files User OR team permissions
["user", "teams"] User's files OR any team's files User OR team permissions

Scope filters are applied when listing files, ensuring users only see files they have permission to access based on Appwrite's permission system.

When using ["user", "team"] scope, files are shown for the current user OR the current team. If no team is selected ($auth.currentTeam), only user-scoped files will display. Use "teams" (plural) instead of "team" (singular) to query all teams the user belongs to, not just the current team.


Display & Manage Files

Storage buckets work identically to local data sources and database tables. Access files using the $x magic method and perform all CRUD operations:

1234567891011121314151617
<div>
    <!-- Upload file -->
    <label role="button">
        <input type="file" @change="if ($event.target.files.length > 0) { $x.assets.$create($event.target.files[0]).then(() => { $event.target.value = ''; }); }" accept="*/*" />
        <span>Upload File</span>
    </label>
    
    <!-- List files -->
    <template x-for="file in $x.assets" :key="file.$id">
        <div class="row gap-2 items-center">
            <span x-text="file.name"></span>
            <button @click="$x.assets.$openUrl(file.$id)" x-icon="lucide:external-link"></button>
            <button @click="$x.assets.$duplicate(file.$id)" x-icon="lucide:copy"></button>
            <button @click="$x.assets.$delete(file.$id)" x-icon="lucide:trash"></button>
        </div>
    </template>
</div>

Storage buckets automatically sync changes in realtime across all active sessions. When one user uploads or deletes a file, all other users see the change immediately without page refresh.

Method details:

Method Parameters Description
$create(file, fileId?, permissions?, onProgress?) file (File object), fileId (string, optional), permissions (array, optional), onProgress (function, optional) Upload a new file. Returns uploaded file. If scope is configured, permissions are automatically set based on user/team
$duplicate(fileId, options?) fileId (string or object with $id), options (object, optional) Duplicate a file. Options: newName, newFileId. Returns duplicated file. If newName is not provided, the file name will be "{originalName} copy"
$delete(fileIdOrArray) fileIdOrArray (string, object with $id, or array) Delete file(s). Returns deleted file(s)
$url(fileId, token?) fileId (string or object with $id), token (string, optional) Get file view URL. Returns URL string
$download(fileId, token?) fileId (string or object with $id), token (string, optional) Get file download URL. Returns URL string
$preview(fileId, options?, token?) fileId (string or object with $id), options (object, optional), token (string, optional) Get file preview URL (images only). Options: width, height, quality, output, etc. Returns preview URL string
$openUrl(fileId, token?) fileId (string or object with $id), token (string, optional) Open file view URL in new tab
$openDownload(fileId, filename?, token?) fileId (string or object with $id), filename (string, optional), token (string, optional) Open file download URL in new tab
$openPreview(fileId, options?, token?) fileId (string or object with $id), options (object, optional), token (string, optional) Open file preview URL in new tab

Files can be automatically linked to database entries when uploaded. Configure the relationship in manifest.json:

manifest.json
{
    "data": {
        "assets": {
            "appwriteBucketId": "your-bucket-id",
            "belongsTo": {
                "table": "projects",
                "id": "$entryId",
                "fileIdsColumn": "fileIds"
            }
        },
        "projects": {
            "appwriteTableId": "your-table-id",
            "storage": {
                "assets": "fileIds"
            }
        }
    }
}

When a file is uploaded with an entryId parameter, it's automatically added to that entry's fileIds array:

<!-- Upload file and link to project entry -->
<button @click="$x.assets.$create(file, null, null, { entryId: project.$id, table: 'projects' })">
    Upload to Project
</button>

Alternatively, link files manually after upload:

<!-- Link file to entry after upload -->
<button @click="
    $x.assets.$create(file).then(uploadedFile => {
        const currentFileIds = project.fileIds || [];
        $x.projects.$update(project.$id, { 
            fileIds: [...currentFileIds, uploadedFile.$id] 
        });
    });
">
    Upload and Link
</button>

See databases for more details on file references.


Properties & Methods

File Properties

Each file includes standard Appwrite properties plus computed properties:

Property Type Description
$id string Unique identifier
name string File name
size number File size in bytes
$formattedSize string Human-readable size (e.g., "2.5 MB")
mimeType string MIME type (e.g., "image/png")
$createdAt string Upload timestamp (ISO format)
$updatedAt string Last update timestamp (ISO format)
$url string View URL
$isImage boolean true if image file
$thumbnailUrl string Thumbnail URL (images only)
<!-- Access file properties -->
<div x-text="file.$id"></div>              <!-- Unique identifier -->
<div x-text="file.name"></div>             <!-- File name -->
<div x-text="file.size"></div>             <!-- File size in bytes -->
<div x-text="file.$formattedSize"></div>   <!-- Human-readable size (e.g., "2.5 MB") -->
<div x-text="file.mimeType"></div>         <!-- MIME type (e.g., "image/png") -->
<div x-text="file.$createdAt"></div>       <!-- Upload timestamp (ISO) -->
<div x-text="file.$updatedAt"></div>       <!-- Last update timestamp (ISO) -->
<div x-text="file.$url"></div>             <!-- View URL -->
<div x-text="file.$isImage"></div>         <!-- Boolean: true if image file -->
<div x-text="file.$thumbnailUrl"></div>    <!-- Thumbnail URL (images only) -->

State Properties

Check data source loading state, errors, and readiness:

Property Type Description
$loading boolean Indicates if data is currently being loaded
$error string | null Error message if an operation failed (null if no error)
$ready boolean Indicates if data has been loaded at least once
<!-- Loading state -->
<small x-show="$x.assets.$loading">Loading files...</small>

<!-- Error state -->
<small x-show="$x.assets.$error" x-text="$x.assets.$error" class="text-error"></small>

<!-- Ready state -->
<small x-show="$x.assets.$ready && !$x.assets.$loading">
    Files loaded: <b x-text="$x.assets.length"></b>
</small>

CRUD Methods

<!-- Upload single file -->
<label role="button">
    <input type="file" @change="if ($event.target.files.length > 0) { $x.assets.$create($event.target.files[0]); }" accept="*/*" />
    <span>Upload</span>
</label>

<!-- Upload with custom file ID -->
<label role="button">
    <input type="file" @change="if ($event.target.files.length > 0) { $x.assets.$create($event.target.files[0], 'custom-id'); }" accept="*/*" />
    <span>Upload with ID</span>
</label>

<!-- Upload with progress callback -->
<label role="button">
    <input type="file" @change="if ($event.target.files.length > 0) { 
        $x.assets.$create($event.target.files[0], null, null, (progress) => { 
            console.log('Progress:', progress + '%'); 
        }); 
    }" accept="*/*" />
    <span>Upload with Progress</span>
</label>

View & Download Methods

<!-- Get view URL -->
<button @click="const url = await $x.assets.$url(file.$id); console.log(url);">
    Get View URL
</button>

<!-- Get view URL with token -->
<button @click="const url = await $x.assets.$url(file.$id, token); console.log(url);">
    Get URL with Token
</button>

View & Download Methods:

Method Parameters Description
$url(fileId, token?) fileId (string or object with $id), token (string, optional) Get file view URL. Returns URL string
$download(fileId, token?) fileId (string or object with $id), token (string, optional) Get file download URL. Returns URL string
$preview(fileId, options?, token?) fileId (string or object with $id), options (object, optional), token (string, optional) Get file preview URL (images only). Options: width, height, quality, output, etc. Returns preview URL string
$openUrl(fileId, token?) fileId (string or object with $id), token (string, optional) Open file view URL in new tab
$openDownload(fileId, filename?, token?) fileId (string or object with $id), filename (string, optional), token (string, optional) Open file download URL in new tab
$openPreview(fileId, options?, token?) fileId (string or object with $id), options (object, optional), token (string, optional) Open file preview URL in new tab

Image Handling

Image files receive special handling with automatic thumbnail generation and preview support:

<!-- Display image with thumbnail -->
<template x-for="file in $x.assets" :key="file.$id">
    <div x-show="file.$isImage">
        <img :src="file.$thumbnailUrl" :alt="file.name" />
        <p x-text="file.name"></p>
    </div>
</template>

<!-- Display full-size image -->
<img :src="file.$url" :alt="file.name" />

<!-- Preview with custom dimensions -->
<button @click="$x.assets.$openPreview(file.$id, { 
    width: 1200, 
    height: 800,
    quality: 95,
    output: 'webp'
})">
    High Quality Preview
</button>

Image preview options:

Option Type Description
width integer Resize width (0-4000)
height integer Resize height (0-4000)
quality integer Image quality (0-100)
output string Format: jpeg, jpg, png, gif, webp
gravity string Crop gravity: center, top-left, top, top-right, left, right, bottom-left, bottom, bottom-right
borderWidth integer Border width in pixels (0-100)
borderColor string Border color (HEX without #)
borderRadius integer Border radius in pixels (0-4000)
opacity number Opacity (0-1, PNG only)
rotation integer Rotation in degrees (-360 to 360)
background string Background color (HEX without #, PNG only)

Next Steps

See databases for managing database entries and linking files to entries.


Powered by Manifest