iOS 7 - NSURLSession可恢复上传

13

我目前正在设计一个系统,用于从应用程序上传多个图像到服务器。文件将存储在本地设备上,当前的想法是将它们分成块,然后逐块上传到服务器,并等待成功消息后再上传下一个。

这个过程对于用户来说应该是无缝的,他们应该按下按钮提交所有图像,然后能够关闭应用程序并使其在后台继续运行。在iOS7中,我发现您可以将上传传递给新的NSURLSession API,并且让它独立于您的应用程序处理上传任务。

我想知道是否有人知道这种传输的可靠性。如果我传递整个图像,如果互联网连接在中途断开会发生什么?后台传输服务会在以后重试吗?我们的想法是上传一张图像,如果在传输过程中失败了,我们可以在稍后恢复连接时从那个点简单地继续上传。

我们的另一个想法是将文件分成块,然后将所有块作为单独的NSURLSessionUploadTasks传递,并假定它们最终都将发送到服务器。

另一个想法是使用以下方法发送第一个块:

uploadTaskWithRequest:fromData:completionHandler:

然后在completionHandler中发送下一个块。 我的问题是,如果在后台处理下一个块,那么...

@property BOOL discretionary = true

这意味着只有在插入电源并连接WiFi时才会发送数据。我需要它能在所有网络上运行,并能够处理中断。

我不需要代码,只是想知道这是否是实现此目标的正确方法。

1个回答

7

我将尝试回答您的一些问题。

如果由于错误而中途停止上传,则您的应用程序应在后台启动,并且您应该能够执行所需的错误处理。在您的情况下,如果您的服务器支持可恢复上传,则应该能够获取偏移量,然后设置另一个任务来上传下一个块。

如果您正在使用配置为在后台运行的NSURLSession,则不能设置具有完成处理程序的上传任务,并且您不能使用NSData对象上传您的块。您唯一的选择是将块写入磁盘,然后使用

uploadTaskWithRequest:fromFile:

我认为这是有道理的,因为NSData对象驻留在应用程序内存中,而后台上传由外部守护程序执行,因此仅将用户沙盒中的文件上传是正确的。同时您需要使用代理来监听回调(当应用程序在前台时),而非使用完成处理程序。
如果您仍然喜欢使用NSData对象,则另一种解决方案是使用创建任务的方式。
downloadTaskWithRequest:

这样,您就可以在请求的正文中设置NSData对象,并将其传递到请求中。您需要使用NSURLMutableRequest来设置请求才能实现这一点。
对于discretionary属性,由于它默认为TRUE,我不确定我们能否做出很大改变。它说传输更可能发生在Wi-Fi和插入电源时,因此可能会在蜂窝网络上发生,但不要以我的话为准,我只是猜测。

如果我正在使用委托,在上一个照片上传完成后,在其完成委托回调中,我可以排队下一个照片上传任务。这样正确吗?-谢谢 - Erben Mo
2
@ErbenMo 请注意,如果在应用程序处于后台时启动后台传输,则配置对象的discretionary属性将被视为true。当设置此标志时,传输更可能在插入电源和Wi-Fi时发生。默认情况下,此值为false。如果在应用程序处于后台时启动任务,则该任务被视为discretionary为true,而不管此属性的实际值如何。因此,您的下一个上传可能要等到您连接到WiFi并插上电源时才会发生。 - Ryan Burke
在后台:如果每次上传后我想向服务器发出一些POST请求,然后再上传一个新文件,这是否可能?每次上传后我们可以获得多少来排队下一个上传。 - Ekra
是的,你可以这样做。当你的应用在后台启动时,你需要为你的上传创建一个新任务,然后调用完成处理程序。在某些情况下,你只有30秒的时间来添加任务、更新UI等操作。 - lost found
根据我的测试,在后台生成相同负载的每个后续任务中,iOS 在任务实际完成之前需要更多的时间(较长的延迟)。 - LostBalloon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接