在iOS中批量下载多个文件 [英] Downloading multiple files in batches in iOS

查看:2372
本文介绍了在iOS中批量下载多个文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,现在需要根据用户选择下载数百个小PDF。我遇到的问题是它需要花费大量时间,因为每次必须打开一个新连接。我知道我可以使用GCD进行异步下载,但是如何批量处理10个左右的文件呢?有没有一个框架可以做到这一点,或者这是我必须建立自己的东西?

I have an app that right now needs to download hundreds of small PDF's based on the users selection. The problem I am running into is that it is taking a significant amount of time because every time it has to open a new connection. I know that I could use GCD to do an async download, but how would I go about doing this in batches of like 10 files or so. Is there a framework that already does this, or is this something I will have to build my self?

推荐答案

这个答案现在是过时。现在不推荐使用 NSURLConnection 并且 NSURLSession 现在可用,它提供了更好的下载一系列文件的机制,避免了太多这里考虑的解决方案的复杂性。请参阅我的其他答案,其中讨论了 NSURLSession

This answer is now obsolete. Now that NSURLConnection is deprecated and NSURLSession is now available, that offers better mechanisms for downloading a series of files, avoiding much of the complexity of the solution contemplated here. See my other answer which discusses NSURLSession.

出于历史考虑,我会在下面保留这个答案。

I'll keep this answer below, for historical purposes.

我'我确定有很多很棒的解决方案,但我写了一点下载管理器来处理在这种情况下,您要下载一堆文件。只需将单独的下载添加到下载管理器中,一旦完成,它将启动下一个排队的下载管理器。您可以指定您希望它同时执行的数量(我默认为4),因此不需要批处理。如果不出意外,这可能会引发一些关于如何在自己的实现中执行此操作的想法。

I'm sure there are lots of wonderful solutions for this, but I wrote a little downloader manager to handle this scenario, where you want to download a bunch of files. Just add the individual downloads to the download manager, and as one finishes, it will kick off the next queued one. You can specify how many you want it to do concurrently (which I default to four), so therefore there's no batching needed. If nothing else, this might provoke some ideas of how you might do this in your own implementation.

注意,这提供了两个优点:

Note, this offers two advantages:


  1. 如果你的文件很大,它永远不会将整个文件保存在内存中,而是在下载时将其流式传输到持久存储。这大大减少了下载过程的内存占用。

  1. If your files are large, this never holds the entire file in memory, but rather streams it to persistent storage as it's being downloaded. This significantly reduces the memory footprint of the download process.

在下载文件时,会有代理协议通知您或下载进度。

As the files are being downloaded, there are delegate protocols to inform you or the progress of the download.

我试图在下载管理器github页面

我应该说,这是为了解决一个特定问题而设计的,我想跟踪下载大文件时的下载进度以及我不希望持有的文件整个内存一次(例如,如果您正在下载100mb文件,您真的想在下载时将其保存在RAM中吗?)。

I should say, though, that this was designed to solve a particular problem, where I wanted to track the progress of downloads of large files as they're being downloaded and where I didn't want to ever hold the entire in memory at one time (e.g., if you're downloading a 100mb file, do you really want to hold that in RAM while downloading?).

虽然我的解决方案可以解决这些问题,但如果您不需要,那么使用操作队列的解决方案就更简单了。事实上,你甚至暗示了这种可能性:

While my solution solves those problem, if you don't need that, there are far simpler solutions using operation queues. In fact you even hint at this possibility:


我知道我可以使用GCD进行异步下载,但我怎么办呢分批处理10个左右的文件。 ...

I know that I could use GCD to do an async download, but how would I go about doing this in batches of like 10 files or so. ...

我不得不说做异步下载让我觉得它是正确的解决方案,而不是试图降低下载性能批量下载的问题。

I have to say that doing an async download strikes me as the right solution, rather than trying to mitigate the download performance problem by downloading in batches.

您谈到使用GCD队列。就个人而言,我只是创建一个操作队列,以便我可以指定我想要的并发操作数,并使用 NSData 方法 dataWithContentsOfURL下载单个文件后跟 writeToFile:atomically:,每次下载都是自己的操作。

You talk about using GCD queues. Personally, I'd just create an operation queue so that I could specify how many concurrent operations I wanted, and download the individual files using NSData method dataWithContentsOfURL followed by writeToFile:atomically:, making each download it's own operation.

因此,例如,假设您有一个要下载的文件的URL数组,可能是:

So, for example, assuming you had an array of URLs of files to download it might be:

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 4;

for (NSURL* url in urlArray)
{
    [queue addOperationWithBlock:^{
        NSData *data = [NSData dataWithContentsOfURL:url];
        NSString *filename = [documentsPath stringByAppendingString:[url lastPathComponent]];
        [data writeToFile:filename atomically:YES];
    }];
}

简单明了。通过设置 queue.maxConcurrentOperationCount ,您可以享受并发性,同时不会因为并发请求过多而破坏您的应用程序(或服务器)。

Nice and simple. And by setting queue.maxConcurrentOperationCount you enjoy concurrency, while not crushing your app (or the server) with too many concurrent requests.

如果您需要在操作完成后收到通知,您可以执行以下操作:

And if you need to be notified when the operations are done, you could do something like:

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 4;

NSBlockOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [self methodToCallOnCompletion];
    }];
}];

for (NSURL* url in urlArray)
{
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSData *data = [NSData dataWithContentsOfURL:url];
        NSString *filename = [documentsPath stringByAppendingString:[url lastPathComponent]];
        [data writeToFile:filename atomically:YES];
    }];
    [completionOperation addDependency:operation];
}

[queue addOperations:completionOperation.dependencies waitUntilFinished:NO];
[queue addOperation:completionOperation];

这会做同样的事情,除非它会调用 methodToCallOnCompletion

This will do the same thing, except it will call methodToCallOnCompletion on the main queue when all the downloads are done.

这篇关于在iOS中批量下载多个文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆