Skip to main content

FileStore API

The FileStore class provides a unified interface for storing and retrieving files in Tyler. It handles file validation, storage, and retrieval, supporting local file system storage with configurable limits and security features.

Initialization

from tyler.storage import FileStore, get_file_store

# Using default configuration
file_store = get_file_store()

# Custom configuration
file_store = FileStore(
base_path="/path/to/files",
max_file_size=100 * 1024 * 1024, # 100MB
max_storage_size=10 * 1024 * 1024 * 1024, # 10GB
allowed_mime_types={"application/pdf", "image/jpeg", "text/plain"}
)

Parameters

ParameterTypeRequiredDefaultDescription
base_pathstrNoTYLER_FILE_STORAGE_PATH or ~/.tyler/filesBase directory for file storage
max_file_sizeintNo50MBMaximum allowed file size in bytes
max_storage_sizeintNo5GBMaximum total storage size in bytes
allowed_mime_typesSet[str]NoCommon typesSet of allowed MIME types

Environment Variables

VariableDescriptionDefault
TYLER_FILE_STORAGE_PATHBase directory for file storage~/.tyler/files
TYLER_MAX_FILE_SIZEMaximum allowed file size in bytes50MB
TYLER_MAX_STORAGE_SIZEMaximum total storage size in bytes5GB
TYLER_ALLOWED_MIME_TYPESComma-separated list of allowed MIME typesCommon types

Methods

save

Save a file to storage.

async def save(
self,
content: bytes,
filename: str,
mime_type: Optional[str] = None
) -> Dict[str, Any]

Parameters

ParameterTypeRequiredDefaultDescription
contentbytesYes-File content as bytes
filenamestrYes-Original filename
mime_typeOptional[str]NoNoneMIME type (auto-detected if not provided)

Returns

{
"id": str, # Unique file ID
"filename": str, # Original filename
"mime_type": str, # Detected/validated MIME type
"storage_path": str, # Relative path in storage
"storage_backend": str, # Always "local" for FileStore
"created_at": datetime, # Creation timestamp
"metadata": {
"size": int # File size in bytes
}
}

Exceptions

  • UnsupportedFileTypeError: If file type is not allowed
  • FileTooLargeError: If file exceeds size limit
  • StorageFullError: If storage capacity is exceeded

get

Get file content from storage.

async def get(
self,
file_id: str,
storage_path: Optional[str] = None
) -> bytes

Parameters

ParameterTypeRequiredDefaultDescription
file_idstrYes-Unique file ID
storage_pathOptional[str]NoNoneStorage path (preferred if available)

Returns

File content as bytes.

Exceptions

  • FileNotFoundError: If file cannot be found

delete

Delete a file from storage.

async def delete(
self,
file_id: str,
storage_path: Optional[str] = None
) -> None

Parameters

ParameterTypeRequiredDefaultDescription
file_idstrYes-Unique file ID
storage_pathOptional[str]NoNoneStorage path (preferred if available)

Exceptions

  • FileNotFoundError: If file cannot be found

validate_file

Validate file content and type.

async def validate_file(
self,
content: bytes,
filename: str,
mime_type: Optional[str] = None
) -> str

Parameters

ParameterTypeRequiredDefaultDescription
contentbytesYes-File content as bytes
filenamestrYes-Original filename
mime_typeOptional[str]NoNoneMIME type (auto-detected if not provided)

Returns

Validated MIME type.

Exceptions

  • UnsupportedFileTypeError: If file type is not allowed
  • FileTooLargeError: If file exceeds size limit

get_storage_size

Get total size of all files in storage.

async def get_storage_size(self) -> int

Returns

Total size in bytes.

get_file_count

Get total number of files in storage.

async def get_file_count(self) -> int

Returns

Number of files.

check_health

Check health of storage system.

async def check_health(self) -> Dict[str, Any]

Returns

{
"status": str, # "healthy" or "unhealthy"
"storage_size": int, # Total storage size in bytes
"file_count": int, # Number of files
"available_space": int, # Available space in bytes
"max_storage_size": int, # Maximum storage size in bytes
"usage_percent": float # Storage usage percentage
}

batch_save

Save multiple files in a single operation.

async def batch_save(
self,
files: List[Tuple[bytes, str, str]]
) -> List[Dict[str, Any]]

Parameters

ParameterTypeRequiredDefaultDescription
filesList[Tuple[bytes, str, str]]Yes-List of (content, filename, mime_type) tuples

Returns

List of metadata dictionaries (same format as save).

batch_delete

Delete multiple files in a single operation.

async def batch_delete(
self,
file_ids: List[str]
) -> None

Parameters

ParameterTypeRequiredDefaultDescription
file_idsList[str]Yes-List of file IDs to delete

list_files

List all file IDs in storage.

async def list_files(self) -> List[str]

Returns

List of file IDs.

Class Methods

get_file_url

Get the full URL for a file based on its relative path.

@classmethod
def get_file_url(cls, relative_path: str) -> str

Parameters

ParameterTypeRequiredDefaultDescription
relative_pathstrYes-Path relative to the base storage path

Returns

The full URL for the file.

get_default_path

Get the default file storage path based on environment or defaults.

@classmethod
def get_default_path(cls) -> Path

Returns

Path object for the default storage location.

initialize_storage

Initialize the file storage directory.

@classmethod
def initialize_storage(cls) -> Path

Returns

Path to the initialized storage directory.

Integration with Attachment Model

The FileStore class works seamlessly with the Attachment model:

from tyler.models.attachment import Attachment
from tyler.storage import get_file_store

# Create an attachment
attachment = Attachment(
filename="document.pdf",
content=pdf_bytes,
mime_type="application/pdf"
)

# Process and store the attachment
await attachment.process_and_store()

# The attachment now has:
# - file_id: Unique identifier in the file store
# - storage_path: Path within the storage system
# - storage_backend: "local" for FileStore
# - status: "stored" if successful
# - attributes: Contains processed content and metadata

# The attributes field includes:
# - type: File type (e.g., "document", "image")
# - url: URL to access the file
# - Additional type-specific information (text extraction, image analysis, etc.)

URL Generation

When an attachment is stored, the FileStore.get_file_url() method is used to generate a URL for the file:

# In Attachment.update_attributes_with_url():
url = FileStore.get_file_url(self.storage_path)
self.attributes["url"] = url

This URL is then used in the Message.to_chat_completion_message() method to include file references in the message content.

Exceptions

ExceptionDescription
FileStoreErrorBase exception for file store errors
FileNotFoundErrorRaised when a file is not found in storage
StorageFullErrorRaised when storage capacity is exceeded
UnsupportedFileTypeErrorRaised when file type is not allowed
FileTooLargeErrorRaised when file exceeds size limit

Best Practices

  1. Configuration

    # Use environment variables for configuration
    os.environ["TYLER_FILE_STORAGE_PATH"] = "/path/to/files"
    os.environ["TYLER_MAX_FILE_SIZE"] = "100000000" # 100MB

    # Initialize once and reuse
    store = get_file_store()
  2. Error Handling

    try:
    result = await store.save(content, filename)
    except UnsupportedFileTypeError:
    print("File type not allowed")
    except FileTooLargeError:
    print("File too large")
    except StorageFullError:
    print("Storage full")
  3. Path Handling

    # Always use storage_path when available
    content = await store.get(file_id, storage_path)

    # Generate URLs using the class method
    url = FileStore.get_file_url(storage_path)
  4. Batch Operations

    # More efficient for multiple files
    results = await store.batch_save([
    (pdf_bytes, "doc1.pdf", "application/pdf"),
    (image_bytes, "image.jpg", "image/jpeg")
    ])

See Also