TUSKit
使用 Swift
编写的 iOS 客户端,用于 TUS 分段上传协议。
通过此客户端,您可以上传常规原始 Data
或文件路径。
使用方法
您可以通过查看示例项目来了解如何实现 TUSKit。
作为起点,请参考 SceneDelegate。
以下是如何实例化 TUSClient
实例的方式。
务必在某个地方存储对客户端的引用。然后像平常一样初始化。
final class MyClass {
let tusClient: TUSClient
init() {
tusClient = TUSClient(server: URL(string: "https://tusd.tusdemo.net/files")!, sessionIdentifier: "TUS DEMO", storageDirectory: URL(string: "TUS")!)
tusClient.delegate = self
}
}
请注意,您可以将自己注册为代表以检索上传的 URL 和可能出现的任何错误。
请注意,您可以向初始化函数传递自己的 URLSession
实例。
您可以通过符合 TUSClientDelegate
接收来自 TUSClient
的更新。
extension MyClass: TUSClientDelegate {
func didStartUpload(id: UUID, client: TUSClient) {
print("TUSClient started upload, id is \(id)")
print("TUSClient remaining is \(client.remainingUploads)")
}
func didFinishUpload(id: UUID, url: URL, client: TUSClient) {
print("TUSClient finished upload, id is \(id) url is \(url)")
print("TUSClient remaining is \(client.remainingUploads)")
if client.remainingUploads == 0 {
print("Finished uploading")
}
}
func uploadFailed(id: UUID, error: Error, client: TUSClient) {
print("TUSClient upload failed for \(id) error \(error)")
}
func fileError(error: TUSClientError, client: TUSClient) {
print("TUSClient File error \(error)")
}
func totalProgress(bytesUploaded: Int, totalBytes: Int, client: TUSClient) {
}
func progressFor(id: UUID, bytesUploaded: Int, totalBytes: Int, client: TUSClient) {
}
}
开始上传
一个 TUSClient
可以上传 Data
或文件路径(URL格式)。
要上传数据,请使用 upload(data:)
方法。
let data = Data("I am some data".utf8)
let uploadId = try tusClient.upload(data: data)
要一次性上传多个数据文件,请使用 uploadMultiple(dataFiles:)
方法。
要上传单个已存储文件,请获取文件路径并将其传递给客户端。
let pathToFile:URL = ...
let uploadId = try tusClient.uploadFileAt(filePath: pathToFile)
要一次性上传多个文件,您可以使用 uploadFiles(filePaths:)
方法。
自定义上传URL和自定义头部
要指定自定义上传URL(例如,用于TransloadIt)或要添加到文件上传的自定义头部,请参阅与上传相关的 uploadURL
和 customHeaders
属性。例如:upload
,uploadFileAt
,uploadFiles
或 uploadMultiple(dataFiles:)
。
测量上传进度
要了解还有多少文件尚未上传,请参阅 remainingUploads
属性。
请注意,没有提供百分比,因为这取决于您定义上传的起点。例如,如果您上传了10个文件,其中3个已完成,那么您处于3/10的状态。但是,如果在这次上传期间添加了2个新文件,这应该计入3/12吗?还是应该考虑为新的上传?因此是0/9。关于添加新上传时已完成上传的计数方式,这取决于您。
对于字节级别的进度,请实现 TUSClientDelegate
协议并将其设置为 TUSClient
的 delegate
属性。
上传ID和上下文
通过开始上传,您将收到一个ID。这些ID也可以通过实现 TUSClientDelegate
时传递给您。您可以使用这些ID来识别哪个文件已经完成或失败(但您也可以使用上下文来做这个,详见下文)。如果您想的话,也可以在失败时删除这些文件。您还可以使用这些ID来重试失败的上传。
请注意,TUSClient
将自动尝试上传几次,但如果最终失败,它将放弃并报告错误。在此之后,您可以调用 retry
方法并再次尝试。
上下文
您可以使用 ID 来监控进度并执行其他任务,例如停止上传。但您也可以使用更丰富的信息传递上下文。TUSKit 将通过各种委托调用来返回此上下文。这样,您就无需跟踪上传 ID 的状态。您可以传递一个小对象包含信息,并且您将从这个对象中收到 TUSKit。
安全通知:TUSKit 将此上下文存储在磁盘上,与文件元数据一起。这是为了在会话之间保持信息。
启动新会话
上传可以在任何时候失败。即使在应用处于后台时。
因此,在启动新应用会话后,我们建议您检查可能出现的任何失败的上传,并相应地采取行动。例如,您可以决定对失败的上传进行一些操作,例如重试、删除或向用户报告。
For instance, here is how you can initialize the client and check its failed uploads. Note that we first fetch the id's, after which retry the uploads.
tusClient = TUSClient(server: URL(string: "https://tusd.tusdemo.net/files")!, sessionIdentifier: "TUS DEMO", storageDirectory: URL(string: "/TUS")!)
tusClient.delegate = self
tusClient.start()
do {
// When starting, you can retrieve the locally stored uploads that are marked as failure, and handle those.
// E.g. Maybe some uploads failed from a last session, or failed from a background upload.
let ids = try tusClient.failedUploadIds()
for id in ids {
// You can either retry a failed upload...
try tusClient.retry(id: id)
// ...alternatively, you can delete them too
// tusClient.removeCacheFor(id: id)
}
} catch {
// Could not fetch failed id's from disk
}
后台上传
当您集成后台上传时,我们强烈建议您检查后台可能发生的任何失败的上传。请参阅 [启动新会话](#Starting a new Session) 获取更多信息。
iOS 可以利用后台 URLSession 来启用后台上传,以便在用户离开您的应用或锁定设备时继续上传。更多详细信息,请参阅 Apple 的文档 background URLSession。文档主要关注下载,但上传遵循大致相同的原理。
为了使集成后台上传尽可能简单,TUSKit 处理了管理 URLSession 及其委托调用等所有复杂细节。作为 TUSKit 的消费者,您只需像下面展示的那样利用 TUSClient
上的新初始化器
do {
tusClient = try TUSClient(
server: URL(string: "https://tusd.tusdemo.net/files")!,
sessionIdentifier: "TUS DEMO",
sessionConfiguration: .background(withIdentifier: "com.TUSKit.sample"),
storageDirectory: URL(string: "/TUS")!,
chunkSize: 0
)
} catch {
// ...
}
设置一切的最简单方法是向 TUSClient
传递一个 URLSession.background
配置。如果您需要不同的配置或不希望有任何后台支持,您可以传递不同的配置。
由于 TUSKit 现在可以在应用程序不再活跃驻留在内存中时运行上传,因此您应该在应用程序启动时始终在 TUSClient
上调用 getStoredUpload
方法来检索所有存储的上传并提取有关哪些上传当前已完成的信息。之后,您可以调用 cleanup
以允许 TUSClient
删除已完成项目的元数据。请参阅示例应用以获取更多详细信息。
重要
当您想支持后台上传时,必须为您的 AppDelegate
的 application(_: handleEventsForBackgroundURLSession:completionHandler:)
方法调用 TUSClient.registerBackgroundHandler(_:)
。此方法接收一个回调,该回调应始终调用传递给 handleEventsForBackgroundURLSession
的 completionHandler
。直接传递完成处理程序是完全可以的。
以下是一个示例
警告:以下信息在 TUSKit 3.1.8 中已弃用。
从 iOS 13 开始,您可以使用 TUSClient
的 scheduleBackgroundTasks()
方法安排后台执行的上传。
安排的任务由 iOS 处理。这意味着每个设备将决定何时在后台上传最佳,例如,当它具有 Wi-Fi 连接并且在夜间较晚的时候。
以示例应用中找到的 SceneDelegate
中的示例为例,您可以相应地安排它们。
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// ... snip
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
tusClient.scheduleBackgroundTasks()
}
}
TUS 协议扩展
客户端默认假定服务器执行了 创建 TUS 协议扩展。如果您的服务器不支持该功能,请确保在客户端初始化器中为 supportedExtensions
参数提供一个空数组。
示例应用
请参考项目内的示例应用了解如何使用 SwiftUI 从 PHPicker 添加照片。您也可以为 UIKit 使用 PHPicker
机制。
并行处理
撰写本文时,此客户端不支持 TUS 的连接选项,但它自动支持单个客户端中的并行上传。它也支持多个客户端。
底层机制
TUSClient
将在报告错误之前重试失败的传输两次(总共三次尝试)。
TUSClient
将尝试完整地上传文件;如果传输中断(例如,连接中断或应用被杀死),它将继续从上次中断的地方继续传输。
TUSClient
将本地存储文件以供上传。它将使用初始化器中传入的 storageDirectory
路径。或者在 documentsdir 内部创建默认目录 /TUS。
TUSClient
将在传输完成后自动移除本地存储的文件。
多个实例
TUSClient
支持多个实例
以进行同时无关的上传。
警告:多个客户端不应共享相同的 storageDirectory
。请为每个客户端提供一个单独的目录以进行操作,否则可能会出现错误。
请注意,从版本 3.0.0 开始的 TUSClient
已不再是单例。
如果您强烈希望拥有单例,您仍然可以使用静态关键字来创建一个。
final class MyClass {
static let tusClient: TUSClient = ...
}
但我们不鼓励这样做,因为这会使测试间的重置变得更加困难,并且在多线程环境中会变得有问题。