2010-05-19 1 views
10

iPhone OS에서 objective-c를 사용하여 URL에서 디스크로 파일을 직접 다운로드하고 싶습니다.iPhone OS에서 파일을 디스크로 직접 다운로드하는 방법은 무엇입니까?

현재 NSURLConnection을 사용하여 synchronousRequest를 보내고 반환 된 NSData를 파일에 씁니다.

메모리 변수를 사용하여 전체 내용 (작은 부분 만)을 저장하지 않고 디스크에 직접 데이터를 쓰려면 어떻게 다운로드 처리를 변경할 수 있습니까? (여전히 요청은 동기식이며 백그라운드 스레드에 있습니다.)

샘플 코드를 제공해 주시면 감사하겠습니다.

미리 답변 해 주셔서 감사합니다.

+0

메모리를 거치지 않고'b' 시스템 콜. 데이터는 라인 어딘가에있는 메모리에 버퍼링됩니다. 이제는 "파일로 다운로드 URL"API를 제공하지만 내부적으로 메모리에 버퍼를 사용하는 라이브러리를 찾을 수 있습니다. –

+0

사실 David 다.하지만 전체 파일 내용을 메모리에 저장할 필요는 없으며 파일에 쓰는 동안 작은 버퍼 만 사용해야한다. 그게 내가 찾고있는거야. – favo

답변

13

이렇게 할 수는 있지만 설정하는 데 약간 복잡합니다. 어떻게해야합니까 :

경고 : 다음 코드는 브라우저에 입력되어 있으며 내 머리 속에 집계되었습니다. 또한 오류 처리가 많지 않습니다. 주의 사항 구현 자.

//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을 만들 수 있지만 바로 연결이 완료 될 때까지 자신을 runloop 회전하여 스레드를 차단하는 것입니다. 또한 사용자 지정 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); 
} 
OS 디스크 파일에 A``URL에서 "복사 데이터가 없기 때문에 말 그대로"직접 디스크에 "데이터를 다운로드하는 것이 가능하지 않을 것
+1

아주 좋은 아이디어! 무한 루프 (우그!)). 그것은 좋은 해결책입니다, 대단히 감사합니다! – favo

+0

글쎄, 솔직히 말해서, 나는 지난 주와 비슷한 것을해야만했고 내가 기억했던 것에서 벗어나려고했다.;) –

+0

당신이주의를 기울 였다면 모든 호출자는 기본 실행 루프가 해당 함수 내에서 실행되기를 원합니다 (특히, 이벤트 핸들러 내부에있는 경우 현재 이벤트 처리가 완료되기 전에 다른 이벤트를 처리하게됩니다.) –