Version 1.34.2+ | Production Ready | Unreal Engine 5.5+
Complete guide to file upload, download, and storage operations using the Supabase UE5 Plugin. This documentation covers the production-ready file operations system with advanced features like chunked uploads, progress tracking, and comprehensive error handling.
The Supabase UE5 Plugin provides robust file operations through the AsyncUploadFile system, designed for production use with:
Blueprint:
Use the “Upload File Async” node with your bucket name, file path, and local file path.
C++:
// Simple file upload
UAsyncUploadFile* UploadTask = UAsyncUploadFile::UploadFileAsync(
this,
Connection,
TEXT("user-avatars"),
TEXT("player123/profile.jpg"),
TEXT("C:/Users/Player/avatar.jpg")
);
UploadTask->OnSuccess.AddDynamic(this, &AMyClass::OnUploadSuccess);
UploadTask->OnFailure.AddDynamic(this, &AMyClass::OnUploadFailure);
UploadTask->Activate();
C++:
UAsyncUploadFile* UploadTask = UAsyncUploadFile::UploadFileWithProgressAsync(
this,
TEXT("game-assets"),
TEXT("textures/environment/tree.png"),
LocalFilePath
);
// Track upload progress
UploadTask->OnProgress.AddDynamic(this, &AMyClass::OnUploadProgress);
UploadTask->OnChunkUploaded.AddDynamic(this, &AMyClass::OnChunkUploaded);
UploadTask->Activate();
// Progress callback
UFUNCTION()
void AMyClass::OnUploadProgress(int64 BytesUploaded, int64 TotalBytes, float ProgressPercentage)
{
UE_LOG(LogTemp, Log, TEXT("Upload Progress: %.1f%% (%lld/%lld bytes)"),
ProgressPercentage, BytesUploaded, TotalBytes);
}
Configure advanced upload behavior using FUploadOptions:
FUploadOptions Options;
Options.UploadMode = EUploadMode::Upsert; // Create or replace
Options.bUseChunkedUpload = true; // Enable chunking for large files
Options.ChunkSize = 2 * 1024 * 1024; // 2MB chunks
Options.MaxFileSize = 100 * 1024 * 1024; // 100MB max file size
Options.bReportProgress = true; // Enable progress events
Options.CacheControl = TEXT("7200"); // Cache for 2 hours
Options.ContentType = TEXT("image/jpeg"); // Override content type
// Add custom metadata
Options.Metadata.Add(TEXT("uploaded_by"), TEXT("player123"));
Options.Metadata.Add(TEXT("game_session"), TEXT("session_456"));
Options.Metadata.Add(TEXT("timestamp"), FDateTime::Now().ToString());
UAsyncUploadFile* UploadTask = UAsyncUploadFile::UploadFileWithOptionsAsync(
this, BucketName, FilePath, LocalFilePath, Options
);
| Mode | Description | Use Case |
|---|---|---|
| Upload | Create new file only | First-time uploads, unique files |
| Upsert | Create or replace existing | Profile pictures, save files |
| Update | Replace existing file only | Update existing content |
The plugin automatically detects content types based on file extensions:
// Automatic content type detection
FString ContentType = UAsyncUploadFile::GetContentTypeFromExtension(TEXT("profile.jpg"));
// Returns: "image/jpeg"
// Supported formats include:
// Images: jpg, jpeg, png, gif, bmp, webp, svg
// Documents: pdf, doc, docx, xls, xlsx, ppt, pptx
// Text: txt, csv, json, xml
// And many more...
For files larger than the chunk size, the plugin automatically uses chunked uploads:
// Configure chunked upload
FUploadOptions Options;
Options.bUseChunkedUpload = true;
Options.ChunkSize = 1024 * 1024; // 1MB chunks
UAsyncUploadFile* UploadTask = UAsyncUploadFile::UploadFileWithOptionsAsync(
this, BucketName, FilePath, LocalFilePath, Options
);
// Monitor chunk progress
UploadTask->OnChunkUploaded.AddDynamic(this, &AMyClass::OnChunkComplete);
UFUNCTION()
void AMyClass::OnChunkComplete(int32 ChunkIndex, int32 TotalChunks)
{
UE_LOG(LogTemp, Log, TEXT("Chunk %d of %d completed"), ChunkIndex, TotalChunks);
}
Control upload behavior during operation:
// Pause upload (preserves progress)
UploadTask->PauseUpload();
// Resume paused upload
UploadTask->ResumeUpload();
// Cancel upload completely
UploadTask->CancelUpload();
// Check upload status
bool bIsUploading = UploadTask->IsUploadInProgress();
float Progress = UploadTask->GetUploadProgress(); // 0.0 - 1.0
Upload from memory instead of local files:
// Upload from TArray<uint8> data
TArray<uint8> FileData;
// ... populate FileData
UAsyncUploadFile* UploadTask = UAsyncUploadFile::UploadFileDataAsync(
this,
BucketName,
FilePath,
FileData,
TEXT("image/png") // Content type
);
The plugin includes comprehensive security validation:
// Bucket name validation
bool bValidBucket = UAsyncUploadFile::IsValidBucketName(TEXT("user-content"));
// File path validation (prevents path traversal)
bool bValidPath = UAsyncUploadFile::IsValidFilePath(TEXT("folder/file.jpg"));
// Automatic sanitization prevents:
// - Path traversal attacks (../)
// - Invalid characters (* ? < > | : ")
// - Empty or malformed paths
Configure file size restrictions:
FUploadOptions Options;
Options.MaxFileSize = 50 * 1024 * 1024; // 50MB limit
// Upload will fail if file exceeds limit
File operations support multiple authentication modes:
// User authentication (default)
UAsyncUploadFile::UploadFileAsync(this, Connection, Bucket, Path, LocalPath,
EAuthenticationToken::User);
// Service key authentication (admin operations)
UAsyncUploadFile::UploadFileAsync(this, Connection, Bucket, Path, LocalPath,
EAuthenticationToken::Service);
// Anonymous authentication
UAsyncUploadFile::UploadFileAsync(this, Connection, Bucket, Path, LocalPath,
EAuthenticationToken::Anonymous);
The plugin provides detailed error information:
UFUNCTION()
void AMyClass::OnUploadFailure(const FString& ErrorMessage)
{
// Common error types:
// - "File too large for upload" (413 response)
// - "Unauthorized - check authentication credentials" (401)
// - "Forbidden - insufficient permissions for upload" (403)
// - "Network error during file upload"
// - "Failed to load file: [filepath]"
// - "Invalid bucket name format"
// - "File size exceeds maximum allowed size"
UE_LOG(LogTemp, Error, TEXT("Upload failed: %s"), *ErrorMessage);
}
Implement custom retry logic for failed uploads:
void AMyClass::UploadWithRetry(int32 MaxRetries)
{
UAsyncUploadFile* UploadTask = UAsyncUploadFile::UploadFileAsync(/*...*/);
UploadTask->OnFailure.AddDynamic(this, &AMyClass::OnUploadFailed);
// Store MaxRetries for retry logic
}
UFUNCTION()
void AMyClass::OnUploadFailed(const FString& ErrorMessage)
{
if (RetryCount < MaxRetries)
{
RetryCount++;
// Retry after delay
GetWorld()->GetTimerManager().SetTimer(RetryTimer, this,
&AMyClass::RetryUpload, 2.0f, false);
}
}
// ✅ Good: Let the async task manage itself
UAsyncUploadFile* UploadTask = UAsyncUploadFile::UploadFileAsync(/*...*/);
UploadTask->Activate();
// Task auto-destructs when complete
// ❌ Avoid: Manual memory management
// Don't store strong references or manually delete
// ✅ Use chunked uploads for large files
FUploadOptions Options;
Options.bUseChunkedUpload = true;
Options.ChunkSize = 1024 * 1024; // Adjust based on network conditions
// ✅ Disable progress reporting for better performance (if not needed)
Options.bReportProgress = false;
// ✅ Set appropriate file size limits
Options.MaxFileSize = 10 * 1024 * 1024; // 10MB for typical use cases
// ✅ All file operations are thread-safe
// ✅ Can be called from any thread
// ✅ Callbacks execute on the game thread
// ✅ Multiple simultaneous uploads supported
void AGameSaveManager::SaveGameToCloud(const FString& SaveData)
{
// Save to local file first
FString SavePath = FPaths::ProjectSavedDir() + TEXT("savegame.json");
FFileHelper::SaveStringToFile(SaveData, *SavePath);
// Upload to Supabase storage
FUploadOptions Options;
Options.UploadMode = EUploadMode::Upsert;
Options.Metadata.Add(TEXT("player_id"), PlayerID);
Options.Metadata.Add(TEXT("level"), CurrentLevel);
Options.Metadata.Add(TEXT("timestamp"), FDateTime::Now().ToString());
UAsyncUploadFile* UploadTask = UAsyncUploadFile::UploadFileWithOptionsAsync(
this, TEXT("game-saves"), FString::Printf(TEXT("%s/save.json"), *PlayerID),
SavePath, Options
);
UploadTask->OnSuccess.AddDynamic(this, &AGameSaveManager::OnSaveUploaded);
UploadTask->OnFailure.AddDynamic(this, &AGameSaveManager::OnSaveUploadFailed);
UploadTask->Activate();
}
void APlayerManager::UploadAvatar(const FString& LocalImagePath)
{
FUploadOptions Options;
Options.UploadMode = EUploadMode::Upsert;
Options.MaxFileSize = 5 * 1024 * 1024; // 5MB limit for avatars
Options.ContentType = TEXT("image/jpeg");
Options.CacheControl = TEXT("86400"); // Cache for 24 hours
FString RemotePath = FString::Printf(TEXT("%s/avatar.jpg"), *PlayerID);
UAsyncUploadFile* UploadTask = UAsyncUploadFile::UploadFileWithOptionsAsync(
this, TEXT("avatars"), RemotePath, LocalImagePath, Options
);
UploadTask->OnProgress.AddDynamic(this, &APlayerManager::OnAvatarUploadProgress);
UploadTask->OnSuccess.AddDynamic(this, &APlayerManager::OnAvatarUploaded);
UploadTask->Activate();
}
UFUNCTION()
void APlayerManager::OnAvatarUploadProgress(int64 BytesUploaded, int64 TotalBytes, float ProgressPercentage)
{
// Update UI progress bar
if (ProgressWidget)
{
ProgressWidget->SetPercent(ProgressPercentage / 100.0f);
}
}
Upload Fails with “Unauthorized”:
Large File Upload Timeouts:
Options.bUseChunkedUpload = trueOptions.ChunkSize = 512 * 1024 (512KB)Path Validation Errors:
* ? < > | : "Memory Issues with Large Files:
Enable detailed logging for troubleshooting:
// In your project settings or code
UE_LOG(LogTemp, Log, TEXT("Starting file upload: %s"), *FilePath);
// The plugin automatically logs:
// - Upload start/completion
// - Chunk progress
// - Error conditions
// - Network responses
| Method | Description |
|---|---|
UploadFileAsync |
Basic file upload from local path |
UploadFileWithProgressAsync |
Upload with progress tracking |
UploadFileWithOptionsAsync |
Upload with advanced configuration |
UploadFileDataAsync |
Upload from memory (TArray) |
| Property | Type | Default | Description |
|---|---|---|---|
UploadMode |
EUploadMode |
Upload | Upload behavior mode |
bUseChunkedUpload |
bool |
true | Enable chunked uploads |
ChunkSize |
int32 |
1MB | Size of each chunk |
MaxFileSize |
int64 |
50MB | Maximum allowed file size |
bReportProgress |
bool |
true | Enable progress events |
CacheControl |
FString |
“3600” | HTTP cache control header |
ContentType |
FString |
Auto-detected | Override content type |
Metadata |
TMap<FString, FString> |
Empty | Custom file metadata |
| Event | Parameters | Description |
|---|---|---|
OnSuccess |
FString Message, bool bSuccess |
Upload completed successfully |
OnFailure |
FString ErrorMessage |
Upload failed with error |
OnProgress |
int64 BytesUploaded, int64 TotalBytes, float ProgressPercentage |
Upload progress update |
OnChunkUploaded |
int32 ChunkIndex, int32 TotalChunks |
Chunk upload completed |
This documentation is maintained by Seven Mountains Labs. For support, visit our Discord community.