iOS - 多个NSURLConnection下载

时间:2012-10-15 12:32:38

标签: iphone objective-c ios xcode cocoa-touch

我正在尝试使用NSURLConnection下载一些文件:

- (void)startDownload {
  NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
  [req addValue:@"Basic XXXXXXXXXXXXXX=" forHTTPHeaderField:@"Authorization"];
  connection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response {
  filepath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:save_name];
  [[NSFileManager defaultManager] createFileAtPath:filepath contents:nil attributes:nil];
  file = [[NSFileHandle fileHandleForUpdatingAtPath:filepath] retain];
  [file seekToEndOfFile];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
  [file seekToEndOfFile];
  [file writeData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection*)connection {
  [file closeFile];
 }

我的文件非常大,所以我必须将我下载的每一块都保存到磁盘中,不能将它们存储在RAM中。问题是,我该如何处理多个下载?

我想在- (void)connectionDidFinishLoading:完成上一次下载之后开始下一次下载,但我想这不是最好的方法。有什么建议吗?

3 个答案:

答案 0 :(得分:2)

对于多次下载,请使用多个NSURLConnection

请注意,在每个委托方法中,您都会传递它所引用的连接。您只需要存储您创建的所有连接(作为属性,或者在数组中,或者其他任何连接,取决于您的设计)。然后,在实施connection: didReceiveData:时,您可以通过比较(使用==)参数与每个存储的连接来检查哪个连接已收到某些数据,您可以相应地对数据进行操作。

答案 1 :(得分:2)

如果你想使用NSURLConnection,我建议你自己创建一个包装连接的下载对象并处理将它写入磁盘的问题。

您可以使用文件名初始化对象以将完成的文件放入,并使用URL来获取文件,例如:

MyDownloadObject *o = [[MyDownloadObject alloc] initWithFilename:filename URL:url];
o.delegate = self;

每个下载对象都会处理它自己的NSURLRequest和NSURLConnection,使用与您的问题完全相同的代码:)

当它完成时,它会告诉你的视图控制器它已下载(可能是通过委托方法,但通知也可以正常工作)。然后,您可以从委托方法告知哪个文件已完成。

- (void)myDownloadObjectFinishedDownload:(MyDownloadObject *)o {
    NSLog(@"File from %@ has been stored at %@", o.URL, o.filename);
}

如果您将MyDownloadObject作为NSOperation的子类,那么您可以使用NSOperationQueue来限制并发下载并监控整体进度等。


如果您不介意使用第三方库,那么ASIHTTPRequest是一个不错的选择,但要注意,它不再被开发。我怀疑堆栈溢出的其他人会推荐更好,更新的库,你可以使用它。

答案 2 :(得分:1)

这就是我想出的:

  • 创建名为downloadQueue
  • 的可变数组
  • 检查您的下载连接是否正在运行,如果是,则排队连接
  • 当您的连接结束时,检查队列,如果队列有成员,则运行队列

实施:(我要标记它的重要部分,请检查每个步骤是否有其他控制措施)

作为私人成员;

...
@property (nonatomic, retain) NSURLConnection *downloadConnection;
@property (nonatomic, retain) NSMutableArray *downloadQueue;
...

修改您的功能,例如;

- (void)startDownload {
  NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
  [req addValue:@"Basic XXXXXXXXXXXXXX=" forHTTPHeaderField:@"Authorization"];

  if (self.downloadConnection)
  {
       if (!self.downloadQueue) self.downloadQueue = [[NSMutableArray alloc] init];
       [self.downloadQueue addObject:request];
       return;
  }
  // else just run your connection
  self.downloadConnection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
}

    - (void)connectionDidFinishLoading:(NSURLConnection*)connection {
  [file closeFile];
  // nil your connection
  self.downloadConnection = nil;
  // check the state of your queue
  [self checkQueue];
 }


 -(void)checkQueue
{
    if (self.downloadQueue)
    {
          if (self.downloadQueue.count > 0)
          {
                NSURLRequest *queueLastObject = [self.downloadQueue lastObject];
                // call the request with downloadConnection and remove it from the queue...
          }
    }
}

注意:此代码仅用于指定实现的概念,应进行编辑以便使用。如果您在任何时候遇到任何问题,请告诉我,我会更新代码。