Skip to main content

Channel files

Organize and manage files within channels using directories and file metadata.

What are channel files?​

Each text channel has a built-in file system where members can upload and organize files. The file system consists of two entities:

  • Directories: Folders that organize files hierarchically within a channel
  • Files: Uploaded content with metadata like name, size, and MIME type

Directories​

A directory is a named folder within a channel. Directories can be nested inside other directories to create a hierarchical structure.

// ChannelDirectory structure
{
id: DirectoryGuid,
parentDirectoryId?: DirectoryGuid, // undefined = root level
name: string
}

When parentDirectoryId is undefined, the directory sits at the channel's root level. Otherwise, it's nested inside the specified parent directory.

Files​

A file represents uploaded content stored in a directory. Files are created by first uploading content through the asset system, then registering the file in a directory.

// ChannelFile structure
{
id: FileGuid,
directoryId: DirectoryGuid,
channelId: ChannelGuid,
name: string,
length: bigint,
mimeType: string,
assetId: AssetGuid,
sha256: Uint8Array,
modifiedAt?: Date
}

The assetId links to the actual content in the asset system. Use the asset URI to download or display the file content.

How channel files work​

Understanding the file creation process and directory structure helps you build file management features.

Creating files​

File creation is a two-step process:

  1. Upload the content: Use rootClient.assets.fileUpload() from your client code to upload the file and receive an upload token
  2. Register the file: Call assetClient.create() to convert the upload token to a permanent asset, then call ChannelFileClient.create() to create the file entry
// Step 1: Client uploads file and gets upload token
// (handled by rootClient.assets.fileUpload in your client code)

// Step 2: Convert token to permanent asset (server)
const assets = await assetClient.create({
tokens: [uploadToken]
});

// Step 3: Register in directory (server)
const file = await rootServer.community.channelFiles.create({
channelId: channelId,
directoryId: directoryId,
uploadTokenUri: uploadToken
});

Directory hierarchy​

Directories form a tree structure within each channel. To build a complete view of the file system:

  1. Call list() to get all directories in the channel
  2. Use parentDirectoryId to reconstruct the hierarchy
  3. Call ChannelFileClient.list() for each directory to get its files
// Get all directories in a channel
const directories = await rootServer.community.channelDirectories.list({
channelId: channelId
});

// Get files in a specific directory
const files = await rootServer.community.channelFiles.list({
channelId: channelId,
directoryId: directoryId
});

Moving files and directories​

Both files and directories can be moved between directories. When moving a directory, all its contents (files and subdirectories) move with it.

Moving requires specifying both the old and new parent:

// Move a directory
await rootServer.community.channelDirectories.move({
channelId: channelId,
id: directoryId,
oldParentDirectoryId: currentParent,
newParentDirectoryId: targetParent
});

// Move a file
await rootServer.community.channelFiles.move({
channelId: channelId,
id: fileId,
oldDirectoryId: currentDirectory,
newDirectoryId: targetDirectory
});

Searching files​

Two search methods help users find files:

MethodScopeUse case
searchSingle channelFind files within the current channel
searchCommunityMultiple channelsFind files across the community

Both methods perform a case-insensitive substring match on file names. Wildcards and regular expressions are not supported.

// Search within a channel
const results = await rootServer.community.channelFiles.search({
channelId: channelId,
search: 'report'
});

// Search across multiple channels
const communityResults = await rootServer.community.channelFiles.searchCommunity({
channelIds: [channel1, channel2, channel3],
search: 'report'
});

Search pagination​

Single-channel search uses cursor-based pagination. Each request returns up to 10 matching files. To retrieve additional results, pass the id of the last file as lastFileId:

// First page
const page1 = await rootServer.community.channelFiles.search({
channelId: channelId,
search: 'report'
});

// Get next page using last file's ID
if (page1.length === 10) {
const lastFile = page1[page1.length - 1];
const page2 = await rootServer.community.channelFiles.search({
channelId: channelId,
search: 'report',
lastFileId: lastFile.id
});
}

Community-wide search does not support pagination. It returns up to 10 matching files per channel, along with a totalCount indicating the total matches in each channel.

Deleting directories​

When you delete a directory, all files and subdirectories within it are also deleted. This is a cascading delete with no recovery. To preserve files, move them to another directory before deleting.

When to use channel files​

  • Document libraries: Create organized folders for team documents, with subdirectories for different projects or topics
  • Media galleries: Build image or video collections with categorized folders
  • File search: Help users find content across channels using the search APIs
  • Automated file management: Move files to archive directories based on age or clean up unused directories
  • Content indexing: Monitor file events to build search indexes or trigger processing workflows