Используя NSURLDownload

В OS X, NSURLDownload предоставляет приложению возможность загрузить содержание URL непосредственно к диску. Это обеспечивает интерфейс, подобный NSURLConnection, добавление дополнительного метода для указания места назначения файла. NSURLDownload может также декодировать обычно используемые схемы кодирования, такие как Макбинэри, BinHex и gzip. В отличие от этого NSURLConnection, данные загрузили использование NSURLDownload не сохранен в системе кэша.

Если Ваше приложение не ограничивается использованием Фундаментальных классов, платформа WebKit включает WebDownload, подкласс NSURLDownload это обеспечивает пользовательский интерфейс для аутентификации.

Загрузка на предопределенное место назначения

Один образец использования для NSURLDownload загружает файл на предопределенное имя файла на диске. Если приложение знает место назначения загрузки, оно может установить его явно использование setDestination:allowOverwrite:. Многократный setDestination:allowOverwrite: сообщения к NSURLDownload экземпляр проигнорирован.

Загрузка запускается непосредственно после получения initWithRequest:delegate: сообщение. Это может быть отменено любое время, прежде чем делегат получит a downloadDidFinish: или download:didFailWithError: сообщение путем отправки загрузки a cancel сообщение.

Пример в Перечислении 3-1 устанавливает место назначения, и таким образом требует, чтобы делегат только реализовал download:didFailWithError: и downloadDidFinish: методы.

Перечисление 3-1  Используя NSURLDownload с предопределенным целевым расположением файла

- (void)startDownloadingURL:sender
{
    // Create the request.
    NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com"]
                                              cachePolicy:NSURLRequestUseProtocolCachePolicy
                                          timeoutInterval:60.0];
 
    // Create the connection with the request and start loading the data.
NSURLDownload  *theDownload = [[NSURLDownload alloc] initWithRequest:theRequest
                                             delegate:self];
    if (theDownload) {
        // Set the destination file.
        [theDownload setDestination:@"/tmp" allowOverwrite:YES];
    } else {
        // inform the user that the download failed.
    }
}
 
 
- (void)download:(NSURLDownload *)download didFailWithError:(NSError *)error
{
    // Dispose of any references to the download object
    // that your app might keep.
    ...
 
    // Inform the user.
    NSLog(@"Download failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
 
- (void)downloadDidFinish:(NSURLDownload *)download
{
    // Dispose of any references to the download object
    // that your app might keep.
    ...
 
    // Do something with the data.
    NSLog(@"%@",@"downloadDidFinish");
}

Делегат может реализовать дополнительные методы настроить обработку аутентификации, перенаправлений сервера и декодирования файла.

Загрузка файла Используя предложенное имя файла

Иногда приложение должно получить целевое имя файла из самих загруженных данных. Это требует, чтобы Вы реализовали метод делегата download:decideDestinationWithSuggestedFilename: и вызовите setDestination:allowOverwrite: с предложенным именем файла. Пример в Перечислении 3-2 сохранил загруженный файл на рабочий стол с помощью предложенного имени файла.

Перечисление 3-2  Используя NSURLDownload с именем файла, полученным из загрузки

- (void)startDownloadingURL:sender
{
    // Create the request.
    NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com/index.html"]
                                             cachePolicy:NSURLRequestUseProtocolCachePolicy
                                             timeoutInterval:60.0];
 
    // Create the download with the request and start loading the data.
NSURLDownload  *theDownload = [[NSURLDownload alloc] initWithRequest:theRequest delegate:self];
    if (!theDownload) {
        // Inform the user that the download failed.
    }
}
 
- (void)download:(NSURLDownload *)download decideDestinationWithSuggestedFilename:(NSString *)filename
{
    NSString *destinationFilename;
    NSString *homeDirectory = NSHomeDirectory();
 
    destinationFilename = [[homeDirectory stringByAppendingPathComponent:@"Desktop"]
        stringByAppendingPathComponent:filename];
    [download setDestination:destinationFilename allowOverwrite:NO];
}
 
 
- (void)download:(NSURLDownload *)download didFailWithError:(NSError *)error
{
    // Dispose of any references to the download object
    // that your app might keep.
    ...
 
    // Inform the user.
    NSLog(@"Download failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
 
- (void)downloadDidFinish:(NSURLDownload *)download
{
    // Dispose of any references to the download object
    // that your app might keep.
    ...
 
    // Do something with the data.
    NSLog(@"%@",@"downloadDidFinish");
}

Загруженный файл хранится на рабочем столе пользователя с именем index.html, который был получен из загруженного содержания. Передача NO к setDestination:allowOverwrite: препятствует тому, чтобы существующий файл был перезаписан загрузкой. Вместо этого уникальное имя файла создается путем вставки порядкового номера после имени файла — например, index-1.html.

Делегату сообщают, когда файл создается на диске, если это реализует download:didCreateDestination: метод. Этот метод также дает приложению возможность определить завершенное имя файла, с которым сохраняется загрузка.

Пример в Перечислении 3-3 регистрирует завершенное имя файла.

Перечисление 3-3  , Регистрирующее завершенное использование имени файла download:didCreateDestination:

-(void)download:(NSURLDownload *)download didCreateDestination:(NSString *)path
{
    // path now contains the destination path
    // of the download, taking into account any
    // unique naming caused by -setDestination:allowOverwrite:
    NSLog(@"Final file destination: %@",path);
}

Это сообщение отправляется делегату после того, как ему дали возможность ответить на download:shouldDecodeSourceDataOfMIMEType: и download:decideDestinationWithSuggestedFilename: сообщения.

Отображение прогресса загрузки

Можно определить прогресс загрузки путем реализации методов делегата download:didReceiveResponse: и download:didReceiveDataOfLength:.

download:didReceiveResponse: метод предоставляет делегату возможность определить ожидаемую длину содержания от NSURLResponse. Делегат должен сбросить прогресс каждый раз, когда он получает это сообщение.

Реализация в качестве примера в Перечислении 3-4 демонстрирует использование этих методов для обеспечения обратной связи прогресса для пользователя.

Перечисление 3-4  , Выводящее на экран прогресс загрузки

- (void)setDownloadResponse:(NSURLResponse *)aDownloadResponse
{
    // downloadResponse is an instance variable defined elsewhere.
    downloadResponse = aDownloadResponse;
}
 
- (void)download:(NSURLDownload *)download didReceiveResponse:(NSURLResponse *)response
{
    // Reset the progress, this might be called multiple times.
    // bytesReceived is an instance variable defined elsewhere.
    bytesReceived = 0;
 
    // Store the response to use later.
    [self setDownloadResponse:response];
}
 
- (void)download:(NSURLDownload *)download didReceiveDataOfLength:(unsigned)length
{
    long long expectedLength = [[self downloadResponse] expectedContentLength];
 
    bytesReceived = bytesReceived + length;
 
    if (expectedLength != NSURLResponseUnknownLength) {
        // If the expected content length is
        // available, display percent complete.
        float percentComplete = (bytesReceived/(float)expectedLength)*100.0;
        NSLog(@"Percent complete - %f",percentComplete);
    } else {
        // If the expected content length is
        // unknown, just log the progress.
        NSLog(@"Bytes received - %d",bytesReceived);
    }
}

Делегат получает a download:didReceiveResponse: сообщение, прежде чем это начнет получать download:didReceiveDataOfLength: сообщения.

Возобновление загрузок

В некоторых случаях можно возобновить загрузку, отмененную или отказавший, в то время как происходящий. Для этого сначала удостоверьтесь, что Ваша исходная загрузка не удаляет свои данные по отказу путем передачи NO к загрузке setDeletesFileUponFailure: метод. Если исходная загрузка перестала работать, можно получить ее данные с resumeData метод. Можно тогда инициализировать новую загрузку с initWithResumeData:delegate:path: метод. Когда загрузка возобновляется, делегат загрузки получает download:willResumeWithResponse:fromByte: сообщение.

Можно возобновить загрузку только если и протокол соединения и тип MIME файла, загружаемого возобновление поддержки. Можно определить, поддерживается ли тип MIME файла с canResumeDownloadDecodedWithEncodingMIMEType: метод.

Декодирование закодированных файлов

NSURLDownload предоставляет поддержку для декодирования Макбинэри, BinHex и gzip форматов файлов. Если NSURLDownload решает, что файл кодируется в поддерживаемом формате, он пытается отправить делегата a download:shouldDecodeSourceDataOfMIMEType: сообщение. Если делегат реализует этот метод, он должен исследовать переданный тип MIME и возврат YES если должен декодироваться файл.

Пример в Перечислении 3-5 сравнивает тип MIME файла и позволяет декодировать Макбинэри и BinHex закодированное содержание.

  Реализация перечисления 3-5 В качестве примера download:shouldDecodeSourceDataOfMIMEType: метод

- (BOOL)download:(NSURLDownload *)download
     shouldDecodeSourceDataOfMIMEType:(NSString *)encodingType
{
    BOOL shouldDecode = NO;
 
    if ([encodingType isEqual:@"application/macbinary"]) {
        shouldDecode = YES;
    } else if ([encodingType isEqual:@"application/binhex"]) {
        shouldDecode = YES;
    } else if ([encodingType isEqual:@"application/x-gzip"]) {
        shouldDecode = NO;
    }
    return shouldDecode;
}