2017-09-14 27 views
0

내 웹 서비스에서 파일 (.json)을 다운로드하고 다운로드가 완료되었습니다. 로컬 SQLlite 데이터베이스에 내용을 압축 해제해야합니다.파일 다운로드가 완료되고 사용할 준비가되었는지 알려주는 방법은 무엇입니까?

NSURLConnection이 다른 스레드에서 파일을 비동기 적으로 다운로드하여 주 스레드를 열어 둘 수 있음을 나타냅니다. 문제는 파일 다운로드가 시작될 때 주 스레드가 분명히 자신이하는 일을 수행한다는 것입니다.이 경우 파일의 내용을 데이터베이스에로드하려고합니다. 이 때 파일이 아직 존재하지 않거나 존재하지만 아직 완료되지 않았습니다.

파일을 실제로 완전히 다운로드하여 사용할 준비가 된 후에 만 ​​파일 내용을 데이터베이스에 입력하는 방법을 어떻게 실행합니까? 있는 NSURLConnection에 대한

-(void)saveJsonToDatabase 
{ 
    NSString *jsonFileToSave = @"drug.json"; 
    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; 
    NSError *jsonError = nil; 

    NSString *jsonFile = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/content/formulary/files/%@", jsonFileToSave]]; 
    NSData *jsonData = [NSData dataWithContentsOfFile:jsonFile]; 
    NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&jsonError]; 

    NSString *formularyTable = [NSString stringWithFormat:@"formulary_%@", [jsonFileToSave stringByDeletingPathExtension]]; 

    FormularyDBManager *formularyDBManagerInstance = [FormularyDBManager new]; 
    [formularyDBManagerInstance insertInto:formularyTable arrayOfDicts:jsonArray]; 
} 

위임 방법 : 당신이 NSURLSessionDownloadTask를 사용하는 경우

-(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response { 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 

    NSString *apiUrl = [NSString stringWithFormat:@"%@",[response URL]]; 
    NSArray *pathComponents = [apiUrl pathComponents]; 
    NSString *areaFolder = [pathComponents objectAtIndex:3]; 
    NSString *fileName = [response suggestedFilename]; 
    NSString *fileType = [fileName pathExtension]; 

    NSString *docsfolderPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    NSString *folderPath = [docsfolderPath stringByAppendingString:[NSString stringWithFormat:@"/content/%@/%@", areaFolder, contentType]]; 

    BOOL isDir; 
    NSFileManager *fileManager= [NSFileManager defaultManager]; 
    if(![fileManager fileExistsAtPath:folderPath isDirectory:&isDir]) 
     if(![fileManager createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:NULL]) 
      NSLog(@"FileDownloader - connection - Error: Create folder failed %@", folderPath); 

    NSString *filePath = [folderPath stringByAppendingPathComponent:fileName]; 

    [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]; 
    connection.file = [NSFileHandle fileHandleForUpdatingAtPath:filePath]; 

    _currentFile = fileName; 
} 
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    [connection.file writeData:data]; 
} 
-(NSCachedURLResponse *)connection:(FileURLConnection *)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse { 
    return nil; 
} 
-(void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    [connection.file closeFile]; 
} 
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    NSLog(@"GetData - connection - error - %@", error); 
} 

답변

1

NSURLSession 및 NSURLSessionDownloadTask는 NSURLConnection이 사용되지 않으므로 계속 사용합니다.

NSURLSessionDownloadTask는 블록 또는 대리인에서 대답 할 수 있으며 블록 변형을 고수 할 수 있습니다.

// Your request 
NSString *conURL = [NSString stringWithFormat:@"%@/%@", apiURL, url]; 
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:conURL]]; 
[request setHTTPMethod:@"GET"]; 

[request addValue:@"application/json" forHTTPHeaderField:(@"content-type")]; 
[request addValue:token forHTTPHeaderField:(@"X-TOKEN")];  

// Create a simple Session 
NSURLSession *session = [NSURLSession sharedSession]; 
// Create the downloadTask 
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable tempLocation, NSURLResponse * _Nullable response, NSError * _Nullable error) { 
    // this block will be called on a async thread when the task is finished. 
    // if no error occurred and we got a path lets store the data. 
    if (!error && tempLocation) { 
     // I pass the location to your function, so it can read the file. 
     [self saveJsonToDatabase:tempLocation]; 
    } 
}]; 
[downloadTask resume]; // don't forget to start the task. 

작업이 완료되거나 실패하면 해당 블록을 호출합니다. tempLocation의 파일은 일시적이며 이후에 삭제됩니다. 계속 유지하려면 다른 경로로 이동해야합니다.

자세한 내용은 내가 무엇을 찾고 있어요에 맞게 수있는이 그것과 같은 NSURLSession + Tasks

+0

사용에 대한 사과의 문서를 읽을 수 있습니다. 파일을 저장할 위치를 정의 할 수 있습니까? 이 클래스를 사용하여 전체 파일을 저장합니다. 'interecpt'하고 내용을 데이터베이스에 저장해야하는 커플입니다. – Ryan

+0

파일을 전달 된 위치로 이동할 수 있습니다. '[[NSFileManager defaultManager] copyItemAtPath : tempLocation toPath : passedFilePath error : nil];'트릭을해야합니다. – Amset

+0

코드를 다시 작성하고 제안 된 변경 사항을 추가 한 후 이제 의도 한대로 작동합니다. 또한이 방법은 걱정할 수있는 대리자 메서드를로드하는 것보다 간단합니다. 감사! – Ryan

0

것은 완료이기 때문에 쉽게 처리 할 수있을 것입니다 데이터베이스에 파일을 저장

-(void)downloadTheFileFrom:(NSString*)url withToken:(NSString*)token 
{ 
    NSString *conURL = [NSString stringWithFormat:@"%@/%@", apiURL, url]; 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:conURL]]; 
    [request setHTTPMethod:@"GET"]; 

    [request addValue:@"application/json" forHTTPHeaderField:(@"content-type")]; 
    [request addValue:token forHTTPHeaderField:(@"X-TOKEN")]; 
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; 

    [conn scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 

    [conn start]; 
    [self saveJsonToDatabase]; 
} 

방법 블록 방법. 완료되면 블록에서 코드를 다운로드합니다. 더하기 NSURLConnection은 더 이상 사용되지 않습니다.