通过 作品存储接口(Title Storage Interface) ,开发人员可以使用 Epic在线服务 (EOS)从云服务器检索加密数据。你通过此接口存储的数据可以被任何用户通过任何可登录的设备访问。尽管与玩家数据存储接口类似,但此接口专门处理与游戏相关的特定数据,而非特定于用户的数据,而且可基于用户的平台、区域或其他条件提供不同版本的文件。有关作品存储接口与玩家数据存储接口间差异的更多详情,参见本文底部的与玩家数据存储的差异小节。
要访问游戏存储接口,请通过平台接口函数 EOS_Platform_GetTitleStorageInterface
获取 EOS_HTitleStorage
句柄。游戏存储接口的所有函数都需要此句柄作为其第一个参数。必须确保 EOS_HPlatform
句柄处于更新状态,以便在完成请求时触发回调。
要使用此接口,必须使用以下额外参数初始化EOS平台:
-
const char* EncryptionKey
:这个64字符的十六进制字符串可构建出256位的密钥,EOS将其用于加密用户数据。Epic的后端服务器不存储此密钥。如果没有密钥,从作品存储接口调用文件管理函数将失败并返回EOS_TitleStorage_EncryptionKeyNotSet
错误代码。 -
const char* CacheDirectory
:这是该接口在数据文件传输期间用于临时存储的完整本地目录路径。它可以是任何位置,一般选择系统的临时目录或游戏的数据目录。如果指定目录不存在,EOS将尝试创建它。你可以对多个用户和产品使用同一目录,EOS将确保其不发生冲突。如果目录有问题,调用文件管理函数将失败,并返回EOS_CacheDirectoryMissing
或EOS_CacheDirectoryInvalid
错误代码。有关可使用文件夹的平台特定限制,请参见EOS平台文档。
文件管理
文件名格式
EOS中的文件名采用以下形式:Directory0/Directory1/DirectoryN/Filename.Extension
"Directory"与"Extension"部分为可选项。每个目录名之后必须加"/"符号,但不能加在他处,也不能作为第一个和最后一个字符。文件名必须使用以下字符:
- 任何字母数字ASCII字符
!
-
_
+
.
'
(
)
文件名不可超过 EOS_TITLESTORAGE_FILENAME_MAX_LENGTH_BYTES
(64)个字符。
查询文件
EOS SDK允许你通过数次查询API调用来检索云上存储的文件信息。你的查询将返回一个或多个文件的元数据,包括每个文件的名称、大小(以字节为单位)和MD5哈希。然后可以请求和管理你自己的元数据副本,并用它来访问或修改文件。由于文件在后端以加密形式存储,因此如文件大小和MD5哈希之类的元数据反映的是加密文件,而非通过开发人员门户上传的原始文件。
当查询对应的回调函数在执行期间,务必从缓存中复制你可能需要的任何信息。数据的生命周期无法保证超过回调函数的持续时间。运行多个查询时这点尤其重要,因为每个成功的查询都可能改变缓存的内容。
大多数函数都包含一个产品用户ID参数(可选项),以便更好地跟踪。你可以在没有产品用户ID的情况下查询数据(通过传递nullptr),但你在开发者门户中设置的用户ID重载项(User ID overrides)将不可用。回调包含你传递的相同的用户产品ID值
查询单个文件
如果只需要一个文件的信息,并且知道该文件名,可以调用 EOS_TitleStorage_QueryFile
函数,传入 EOS_TitleStorage_QueryFileOptions
结构,初始化如下:
属性 | 值 |
---|---|
ApiVersion | EOS_TITLESTORAGE_QUERYFILEOPTIONS_API_LATEST |
LocalUserId | (可选项)正在请求文件数据的本地用户的 EOS_ProductUserId |
Filename | 正在查询的文件名 |
操作完成后,EOS将运行结构为 EOS_TitleStorage_QueryFileCallbackInfo
的回调(类型为 EOS_TitleStorage_OnQueryFileCompleteCallback
)。如果调用成功,则EOS现在已将文件相关数据存入缓存中。
按标签查询多个文件
要一次性查询多个文件,或在不知确切文件名的情况下查询文件,必须先通过开发人员门户将标签应用于你的文件。然后EOS SDK可以基于这些标签查询文件。文件标记是字符串,其使用的格式规则与EOS文件名相同。以此方式查询文件时,必须提供一个或多个标签,EOS SDK将检索包含其中至少一个标记的所有文件的列表。为此需调用 EOS_TitleStorage_QueryFileListOptions
数据结构和 EOS_TitleStorage_QueryFileList
,其初始化如下:
属性 | 值 |
---|---|
ApiVersion | EOS_TITLESTORAGE_QUERYFILELISTOPTIONS_API_LATEST |
LocalUserId | (可选项)正在请求文件数据的本地用户的 EOS_ProductUserId |
NumTags | 标签列表中的标签数量(必须是正数值) |
ListOfTags | 要为其查询文件的标签数组(ASCII字符串) |
完成时,EOS将返回数据结构为 EOS_TitleStorage_QueryFileListCallbackInfo
的回调函数(类型为 EOS_TitleStorage_OnQueryFileListCompleteCallback
)。如果调用成功,数据结构将包含找到的文件数量,且EOS缓存中包含这些文件的相关信息。
查询所有文件
作品存储接口不会提供特定的API调用来查询所有文件。但是,如果将特定标签应用于你上传的每个文件,则可以使用该标签以及 EOS_TitleStorage_QueryFileListOptions
来检索所有文件的相关数据。
检查缓存的文件信息
一旦EOS检索和缓存了一个或多个文件的相关信息,你可以通过调用 EOS_TitleStorage_CopyFileMetadataByFilename
以及特定文件的文件名来检索该文件的相关信息,或通过调用 EOS_TitleStorage_CopyFileMetadataAtIndex
以及文件在缓存内的索引值(0为起点)。如果你需要知道缓存中的文件数量,可以调用 EOS_TitleStorage_GetFileMetadataCount
。不再需要此信息的副本时,调用 EOS_TitleStorage_FileMetadata_Release
以释放它占用的内存。
查询EOS有关单个文件的信息之后,EOS_TitleStorage_GetFileMetadataCount
可能显示缓存中包含的多个文件。如果之前查询的结果仍保留在缓存中,就可能会发生这种情况。这种情况下,最佳操作是检查并确保 EOS_TitleStorage_QueryFileCallbackInfo
中的 ResultCode
是 EOS_Success
,并调用 EOS_TitleStorage_CopyFileMetadataByFilename
以访问其信息。成功查询多个文件时,将删除之前缓存的元数据。
访问文件
作品存储接口支持从云异步读取文件。读取是一种流操作,EOS提供了一些句柄,用于检查流的进度,或限制/中断流送。
读取文件
要从云(或你的本地缓存)中读取已知名称的文件,请调用 EOS_TitleStorage_ReadFile
。你将需要传入 EOS_TitleStorage_ReadFileOptions
,其初始化如下:
属性 | 值 |
---|---|
ApiVersion | EOS_TITLESTORAGE_READFILEOPTIONS_API_LATEST |
LocalUserId | (可选项)正在读取请求文件的本地用户账号ID |
Filename | 要读取的文件的名称 |
ReadChunkLengthBytes | 要在单个 EOS_TitleStorage_OnReadFileDataCallback 调用中读取的最大数据量 |
ReadFileDataCallback | 回调函数,用于处理传入的数据,并能提早停止传输 |
FileTransferProgressCallback | 可选回调函数,用于通知你传输进度;如果设置了则至少调用一次 |
此函数返回 EOS_HTitleStorageFileTransferRequest
句柄,可用于检查传输进度,获取文件名,或取消传输。传输期间可随时调用 EOS_TitleStorageFileTransferRequest_GetFileRequestState
以轮询其当前状态,调用 EOS_TitleStorageFileTransferRequest_GetFilename
以检查待传输文件的名称,或调用 EOS_TitleStorageFileTransferRequest_CancelRequest
以取消请求(不会产生错误)。如果愿意从EOS接收更新而非直接轮询传输,在发起传输时请提供有效的 EOS_TitleStorage_OnFileTransferProgressCallback
函数(作为 FileTransferProgressCallback
参数),并且EOS将定期(使用 EOS_TitleStorage_FileTransferProgressCallbackInfo
参数)调用它以告知你文件传输的进度。如果选择此路径,则可保证至少会调用你的回调函数一次。虽然回调函数和句柄的用途非常相似,并且大部分用例都不需要同时用到两者,但使用回调函数时并不排除使用句柄。
当文件的一部分通过时,你的 ReadFileDataCallback
(类型为 EOS_TitleStorage_OnReadFileDataCallback
)将使用 EOS_TitleStorage_ReadFileDataCallbackInfo
类型的参数运行。此结构包含来自文件的实际数据块,以及指示该数据块是否是最后一个块的变量。它还有一个枚举返回类型 EOS_TitleStorage_EReadResult
,可用其指示EOS继续传输、因错误终止传输或取消传输而不报告错误。
文件传输完成后,EOS将使用 EOS_TitleStorage_ReadFileCallbackInfo
参数运行你的 EOS_TitleStorage_OnReadFileCompleteCallback
回调函数。此参数指示成功或失败,并包括文件名。
EOS会在本地缓存文件,以加快之后的读取操作。这些文件将使用你在EOS平台初始化期间提供的密钥进行加密。发送到你的 ReadFileDataCallback
函数的数据块不会加密。
以下时间轴图显示一个假想的正在进行的读取操作:
连续下载多个文件时,可以先查询文件列表,缓存元数据,然后执行下载,这样可以提高效率。这可避免必须执行多个查询和等待每次文件下载的结果。
数据缓存和加密
作品存储接口将文件数据和元数据缓存在客户端系统的 CacheDirectory
文件夹内。EOS将尽可能使用这些数据,而非使用MD5校验和测试从云中流送数据,从而避免数据损坏,并确定本地缓存文件何时与云上的版本一致,在这种情况下,读取操作可以在一个回调周期内完成。任何成功的读取操作都会更新缓存。EOS在关闭时不清除缓存,因此未来会话中可以重复使用缓存文件。
始终使用EOS平台初始化期间你提供的密钥对作品存储文件进行加密保存。加密密钥本身不存储在云上,以免Epic Games和恶意第三方使用密钥访问数据。加密密钥对于同一件产品的所有用户都是相同的。
EOS会定期自动清除过期或未使用的缓存文件,但你可以通过调用 EOS_TitleStorage_DeleteCache
函数手动清除缓存(例如,如果你的本地存储空间很少)。你将需要传入 EOS_TitleStorage_DeleteCacheOptions
,其初始化如下:
属性 | 值 |
---|---|
ApiVersion | EOS_TITLESTORAGE_DELETECACHEOPTIONS_API_LATEST |
LocalUserId | 本地用户的账号ID |
大多数情况下不需要使用此函数。删除缓存会增加系统的下载次数,并对游戏和后端服务的性能产生负面影响。
文件覆盖
你可以在游戏代码中管理默认文件,但最好提供这些文件的替代版本。例如,每个游戏服务器可能都有你想使用的自有配置设置文件。你必须通过开发人员门户管理这些替代文件。你可以在门户中配置文件的设置,包括指定谁应该接收替代文件。当你通过作品存储接口查询文件时,该接口会在适用情况下返回替代文件。
如需更多信息,请参阅作品存储管理文档。
文件解密工具
你可以使用 文件解密工具(File Decryption Tool) 来创建新文件或解密作品存储 或 玩家数据存储 中的数据。
使用限制
Title存储使使用Epic在线服务(EOS)的开发者能够从云服务器上发布游戏特定的加密数据。数据可以通过标签进行分组,并向所有平台的所有用户提供。关于限制(throttling)、使用配额和最佳实践的信息,请参见服务使用限制。
目前,作品存储没有单个文件大小的限制,其他限制请参见下表:
功能 | 服务限制 |
---|---|
目录大小限制 | 10 GB |
文件最大数量 | 100 |
与玩家数据存储的差异
作品存储接口和玩家数据存储接口都可用于处理基于云的数据文件,但处理方式不同,目的也不同。以下是两者的主要差异:
-
虽然玩家数据存储接口也可以创建、修改和删除文件,但作品存储接口仅查询和下载通过开发人员门户放到云中的文件。
-
作品存储接口基于每个产品处理文件;这些文件对于该产品的所有用户是通用的。玩家数据存储接口基于每个用户处理文件,且这些文件是各个用户的私有文件。
-
这两种接口的文件加密方式不同。详情请参见数据缓存和加密小节。
-
作品存储接口支持条件式文件覆盖,使开发人员能够基于各种条件提供不同版本的文件。详情请参见文件覆盖小节。
-
使用作品存储接口查询文件时,可以使用标记系统将相关文件分为一组。
-
由于作品存储接口不上传文件,因此无需考虑用户节流问题。