Как загрузить файлы непосредственно на диск на iPhone OS?

Я хотел бы загрузить файлы непосредственно от URL до диска с помощью цели-c на iPhone OS.

В настоящее время я использую NSURLConnection для отправки synchronousRequest, пишущий возвращенный NSData в файл.

Как я могу изменить обработку загрузки (все еще имеющий запрос, являющийся синхронным, это уже находится в фоновом потоке) записать данные непосредственно в диск, не используя переменные памяти для хранения полного содержания (только мелкие детали)?

Пример кода ценился бы.

Спасибо всем заранее за Ваши ответы!

10
задан favo 19 May 2010 в 19:28
поделиться

1 ответ

Вы можете это сделать, но это немного сложно настроить. Вот как бы я это сделал:

предупреждение: следующий код был набран в браузере и скомпилирован в моей голове. Кроме того, здесь не так много обработки ошибок. Будьте внимательны, разработчик.

//NSURLConnection+DirectDownload.h
@interface NSURLConnection (DirectDownload)

+ (BOOL) downloadItemAtURL:(NSURL *)url toFile:(NSString *)localPath error:(NSError **)error;

@end

//NSURLConnection+DirectDownload.m
@implementation NSURLConnection (DirectDownload)

+ (BOOL) downloadItemAtURL:(NSURL *)url toFile:(NSString *)localPath error:(NSError **)error {
  NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:url];
  //configure the request, or leave it as-is

  DirectDownloadDelegate * delegate = [[DirectDownloadDelegate alloc] initWithFilePath:localPath];
  NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  [delegate autorelease];
  [request release];

  while ([delegate isDone] == NO) {
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
  }

  [connection release];

  NSError * downloadError = [delegate error];
  if (downloadError != nil) {
    if (error != nil) { *error = [[downloadError retain] autorelease]; }
    return NO;
  }

  return YES;
}

//DirectDownloadDelegate.h
@interface DirectDownloadDelegate : NSObject {
  NSError *error;
  NSURLResponse * response;
  BOOL done;
  NSFileHandle * outputHandle;
}
@property (readonly, getter=isDone) BOOL done;
@property (readonly) NSError *error;
@property (readonly) NSURLResponse * response;

@end

//DirectDownloadDelegate.m
@implementation DirectDownloadDelegate
@synthesize error, request, done;

- (id) initWithFilePath:(NSString *)path {
  if (self = [super init]) {
    if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
      [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
    }
    [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
    outputHandle = [[NSFileHandle fileHandleForWritingAtPath:path] retain];
  }
  return self;
}

- (void) dealloc {
  [error release];
  [response release];
  [outputHandle closeFile];
  [outputHandle release];
  [super dealloc];
}

- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)anError {
  error = [anError retain];
  [self connectionDidFinishLoading:connection];
}

- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)someData {
  [outputHandle writeData:someData];
}

- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)aResponse {
  response = [aResponse retain];
}

- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
  done = YES;
}

Основная идея состоит в том, что вы создаете стандартное NSURLConnection , которое обычно является асинхронным, но просто блокируете поток, вращая цикл выполнения самостоятельно, пока соединение не будет установлено. Вы также можете использовать настраиваемый делегат подключения по URL-адресу, чтобы просто передать любые данные, получаемые подключением, непосредственно в файл.

Теперь вы можете сделать:

NSError * downloadError = nil;
BOOL ok = [NSURLConnection downloadItemAtURL:someURL toFile:someFile error:&downloadError];
if (!ok) {
  NSLog(@"ack there was an error: %@", error);
} else {
  NSLog(@"file downloaded to: %@", someFile);
}
13
ответ дан 3 December 2019 в 23:48
поделиться