Jak pobierać pliki bezpośrednio na dysk na iPhone os?

Chciałbym pobrać pliki bezpośrednio z adresu URL na dysk za pomocą objective-c na iPhone os.

Obecnie używam NSURLConnection, aby wysłać zapytanie synchrousrequest, zapisując zwrócone NSData do pliku.

Jak mogę zmienić obsługę pobierania (wciąż mając żądanie synchroniczne, jest już w wątku w tle), aby zapisać dane bezpośrednio na dysk, nie używając zmiennych pamięci do przechowywania pełnej zawartości (tylko małe części)?

Próbka kod będzie mile widziany.

Z góry dziękuję wszystkim za odpowiedzi!

Author: favo, 2010-05-19

1 answers

Możesz to zrobić, ale konfiguracja jest trochę skomplikowana. Oto jak bym to zrobił:

Uwaga: poniższy kod został wpisany w przeglądarce i skompilowany w mojej głowie. Ponadto, nie ma wiele obsługi błędów. / Align = "Left" /

//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;
}

Podstawową ideą jest to, że tworzysz standard NSURLConnection, który jest zwykle asynchroniczny, ale po prostu blokujesz wątek, obracając runloop samodzielnie, aż do zakończenia połączenia. Używasz również niestandardowego delegata połączenia url, aby po prostu podłączyć wszelkie dane, które połączenie odbiera bezpośrednio do pliku.

Możesz teraz zrobić:

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
Author: Dave DeLong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-19 19:53:37