iOS 7 NSURLSession Download multiple files in Background

前端 未结 1 709
再見小時候
再見小時候 2021-02-04 20:53

I want to download a List of files using NSUrlSession.

I have a variable for counting the successful downloads @property (nonatomic) int downloadsSuccessfulCounter

1条回答
  •  滥情空心
    2021-02-04 21:10

    So, as I mentioned in my comments, the issue is that each File requires a unique NSURLSession, and each NSURLSession requires a NSURLSessionConfiguration with a unique identifier.

    I think that you were close - and probably more proper than me in certain aspects... You just need to create a structure to pass unique IDs into unique Configurations, to populate unique Sessions (say that 10x fast).

    Here's what I did:

    /* * Retrieves the List of Files to Download * Also uses the size of that list to instantiate items * In my case, I load a character returned text file with the names of the files that I want to download */

    - (void) getMediaList {
    
        NSString *list = @"http://myserver/media_list.txt";
        NSURLSession *session = [NSURLSession sharedSession]; // <-- BASIC session
        [[session dataTaskWithURL:[NSURL URLWithString:list]
                completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    
                    NSString *stringFromData = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
    
                    // Populate Arrays
                    REMOTE_MEDIA_FILE_PATHS = [stringFromData componentsSeparatedByString:@"\n"];
                    [self instantiateURLSessions:[REMOTE_MEDIA_FILE_PATHS count]]; 
    
    
                    // Start First File
                    [self getFile:[REMOTE_MEDIA_FILE_PATHS objectAtIndex:downloadCounter]:downloadCounter]; // this variable is 0 at the start
                }]
         resume];
    }
    

    /* * This sets Arrays of Configurations and Sessions to the proper size * It also gives a unique ID to each one */

    - (void) instantiateURLSessions : (int) size {
    
        NSMutableArray *configurations = [NSMutableArray array];
        NSMutableArray *sessions = [NSMutableArray array];
    
        for (int i = 0; i < size; i++) {
            NSString *index = [NSString stringWithFormat:@"%i", i];
            NSString *UniqueIdentifier = @"MyAppBackgroundSessionIdentifier_";
            UniqueIdentifier = [UniqueIdentifier stringByAppendingString:index];
    
            [configurations addObject: [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:UniqueIdentifier]];
            [sessions addObject:[NSURLSession sessionWithConfiguration: [configurations objectAtIndex:i]  delegate: self delegateQueue: [NSOperationQueue mainQueue]]];
        }
    
        NSURL_BACKGROUND_CONFIGURATIONS = [NSArray arrayWithArray:configurations];
        NSURL_BACKGROUND_SESSIONS = [NSArray arrayWithArray:sessions];
    }
    

    /* * This sets up the Download task for each file, based off of the index of the array * It also concatenates the path to the actual file */

    - (void) getFile : (NSString*) file :(int) index {
        NSString *fullPathToFile = REMOTE_MEDIA_PATH; // Path To Server With Files
        fullPathToFile = [fullPathToFile stringByAppendingString:file];
    
        NSURL *url = [NSURL URLWithString:fullPathToFile];
        NSURLSessionDownloadTask *downloadTask = [[NSURL_BACKGROUND_SESSIONS objectAtIndex:index ] downloadTaskWithURL: url];
        [downloadTask resume];
    
    }
    

    /* * Finally, in my delegate method, upon the completion of the download (after the file is moved from the temp data), I check if I am done and if not call the getFiles method again with the updated counter for the index */

    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
    {
    
        // Get the documents directory URL
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:LOCAL_MEDIA_PATH];
        NSURL *customDirectory = [NSURL fileURLWithPath:dataPath];
    
        // Get the file name and create a destination URL
        NSString *sendingFileName = [downloadTask.originalRequest.URL lastPathComponent];
        NSURL *destinationUrl = [customDirectory URLByAppendingPathComponent:sendingFileName];
    
        // Move the file
        NSError *error = nil;
        NSFileManager *fileManager = [NSFileManager defaultManager];
        if ([fileManager moveItemAtURL:location toURL:destinationUrl error: &error]) {
    
            // List
            [self listCustomDirectory];
    
            if(downloadCounter < [REMOTE_MEDIA_FILE_PATHS count] -1) {
                // Increment Counter
                downloadCounter++;
    
                // Start Next File
                [self getFile:[REMOTE_MEDIA_FILE_PATHS objectAtIndex:downloadCounter]:downloadCounter];
            }
            else {
                // FINISH YOUR OPERATION / NOTIFY USER / ETC
            }
        }
        else {
            NSLog(@"Damn. Error %@", error);
            // Do Something Intelligent Here
        }  
    }
    

    0 讨论(0)
提交回复
热议问题