Skip to main content

Listing and reading files from Title Storage

You can upload game-wide data to Title Storage via the Epic Games Portal, and then download it via the Title File interface at runtime. You can access the Title File interface even if the local user isn't signed in yet.

The Title Storage service in the Dev Portal also allows you to override what file content is served based on the user's ID or the client ID.

List files available in Title Storage

To interact with Title Storage, first get the title file interface:

#include "OnlineSubsystem.h"
#include "OnlineSubsystemUtils.h"

// ...
IOnlineSubsystem *Subsystem = Online::GetSubsystem(this->GetWorld());
IOnlineTitleFilePtr TitleFile = Subsystem->GetTitleFileInterface();

Register the event handler so you know when the enumeration has completed. EnumerateTitleFilesDelegateHandle is declared as an FDelegateHandle.

this->EnumerateTitleFilesDelegateHandle =
TitleFile->AddOnEnumerateFilesCompleteDelegate_Handle(FOnEnumerateFilesComplete::FDelegate::CreateUObject(
this,
&UMyClass::HandleEnumerateTitleFilesCompelte));

Then call EnumerateTitleFiles like so:

// EOS does not support anything other than the default value being passed in here.
FPagedQuery PagedQuery = FPagedQuery();
TitleFile->EnumerateFiles(PagedQuery);
void UMyClass::HandleEnumerateTitleFilesCompelte(
bool bWasSuccessful,
const FString &Error)
{
if (!bWasSuccessful)
{
// Enumeration didn't succeed, return error.
return;
}

// Deregister the event handler.
IOnlineSubsystem *Subsystem = Online::GetSubsystem(this->GetWorld());
IOnlineTitleFilePtr TitleFile = Subsystem->GetTitleFileInterface();

TitleFile->ClearOnEnumerateFilesCompleteDelegates(this->EnumerateTitleFilesDelegateHandle);
this->EnumerateTitleFilesDelegateHandle.Reset();
}

After enumeration, you can read the list of available files by calling GetFileList:

TArray<FCloudFileHeader> Files;
TitleFile->GetFileList(Files);
TArray<FString> FileNames;
FileNames.Reserve(Files.Num());
for (const auto& It : Files)
{
FileNames.Add(It.FileName);
}

Reading a file from Title Storage

When reading files from Title Storage, they might need to be transparently downloaded first, so reading files is an asynchronous operation.

First, register the event handler for when the file read is complete. HandleReadFileDelegateHandle is declared as an FDelegateHandle.

this->HandleReadFileDelegateHandle =
UserCloud->AddOnReadFileCompleteDelegate_Handle(FOnReadFileComplete::FDelegate::CreateUObject(
this,
&UMyClass::HandleReadFileDelegateHandle));

Then call ReadFile, with the name of the file you want to read:

if (!TitleFile->ReadFile(FileName))
{
// Unable to start reading file. The callback will not be fired, so you
// should unregister it and return an error.
IOnlineSubsystem *Subsystem = Online::GetSubsystem(this->GetWorld());
IOnlineTitleFilePtr TitleFile = Subsystem->GetTitleFileInterface();
TitleFile->ClearOnReadFileCompleteDelegate_Handle(this->HandleReadFileDelegateHandle);
this->HandleReadFileDelegateHandle.Reset();
return;
}

When your callback fires, you'll want to handle any errors (check bWasSuccessful), and then deregister the event handler:

void UMyClass::HandleReadFileDelegateHandle(
bool WasSuccessful,
const FString &FileName)
{
IOnlineSubsystem *Subsystem = Online::GetSubsystem(this->GetWorld());
IOnlineTitleFilePtr Title = Subsystem->GetTitleFileInterface();
TitleFile->ClearOnReadFileCompleteDelegate_Handle(this->HandleReadFileDelegateHandle);
this->HandleReadFileDelegateHandle.Reset();

if (!bWasSuccessful)
{
// Failed to read title file, return error.
}
else
{
TArray<uint8> FileContents;
if (!TitleFile->GetFileContents(UserId, FileName, FileContents))
{
// Failed to read title file, return error.
}
else
{
// FileContents has been populated with the file data.
}
}
}