Detailed Interpretation of AFNetworking File Breakpoint Download

I've seen many downloads of breakpoints written by people, including those on GitHub, but there's a common feature that doesn't meet the demand, or that's a little over-encapsulated. Over-encapsulated is a little painful. So buddy, I decided to come. Of course, I'm not a fuel-efficient lamp. Before I make my point, I'll make a mockery of the code downloaded from the next brain-damaged breakpoint. You can do it on your Xcode, but don't forget to import it. AFNetworking 3.0 bag; let's enjoy it first.  




I totally don't understand why Shenma calls breakpoint to download and talk nonsense about calves.

First, the above method is more suitable for downloading small files, such as downloading a picture or audio or something.

Secondly, breakpoint download means that I turn off the APP, and next time I come in, I can continue my download and install the above method. Can Nima APP download a tens of megabytes file when it closes?  





Here are my methods and ideas

File is actually a binary stream in the final analysis; file download can be understood as splitting a large file into small pieces, from the server to the client through the network piece by piece, which is more abstract, to draw a picture.



Assuming that there is a file File size of 1200kb on the server, we can understand it as several blocks (here I divide it into 12 blocks for demonstration) each block is 100kb (ideally just for demonstration). The downloaded file must be downloaded from the first block to the twelfth block so that it can be combined into a complete file.

In fact, the NSURLRequest class provides us with a method.

- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(NSString *)field;


So how do we use it? We usually use this in breakpoint Downloads

 [request setValue:@"bytes=120-" forHTTPHeaderField:@"Range"];

bytes=120 - Is this a ghost again?

Actually, this ghost is quite powerful. That's the block we mentioned above.

If you don't use this method, download from 0 to the last byte by default

We have the following formats

1: bytes=120 - - means downloading from 120 bytes onwards (including 120 bytes, which is not important in fact)

2: bytes=120-1234) means downloading 120-1234 bytes of data (including 120 bytes, including 1234)

3:bytes=0-120

4:bytes=-120) Represents the last 120 bytes of download.

5: bytes=120-1234,1567-2456 Represents downloading 120-1234 bytes of data and 1567-2456



Focus on this approach ,


 task = [manager dataTaskWithRequest:request uploadProgress:NULL downloadProgress:^(NSProgress * _Nonnull downloadProgress) {

    

        fileTotalSize = downloadProgress.totalUnitCount;

        

    } completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {

         NSLog(@"%ld ======     ", fileTotalSize);

    }];



This method is to get the file size when downloading. If you download from 0 bytes, download Progress. TotUnitCount That's the total size of the file. If you set bytes=120 - then download Progress. totalUnitCount It's important to remove 120 of the total size of the file.

Okay, post the code... First you need to import AFNetworking and then run it on the simulator, because the address can be printed on the simulator.



#import "ViewController.h"
#import "AFNetworking.h"



#define URL @"http://7fvipe.com1.z0.glb.clouddn.com/322196.jpg"

#define FILEPATH [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"download/org"]
#define FILEPATHName [FILEPATH stringByAppendingPathComponent:@"test8.png"]

@interface ViewController (){
    
    NSURLSessionDataTask *task;
    
    NSFileHandle *fileHandle;
    UILabel *showLabel;
    

    __block  NSInteger  fileCompleteSize ;
    __block  NSUInteger fileTotalSize ;

}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSLog(@"%@",FILEPATH);
    
    
    fileCompleteSize = 0;
    fileTotalSize = 0;
    
    
    UIButton *button1 = [[UIButton alloc ] init];
    button1.frame = CGRectMake(10, 40, 80, 100);
    [button1 setTitle:@"Start downloading" forState:UIControlStateNormal];
    [button1 addTarget:self action:@selector(button1) forControlEvents:UIControlEventTouchUpInside];
    button1.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:button1];
    
    
    button1 = [[UIButton alloc ] init];
    button1.frame = CGRectMake(110, 40, 80, 100);
    [button1 setTitle:@"Suspend Download" forState:UIControlStateNormal];
    [button1 addTarget:self action:@selector(button2) forControlEvents:UIControlEventTouchUpInside];
    button1.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:button1];
    
    
    
    button1 = [[UIButton alloc ] init];
    button1.frame = CGRectMake(210, 40, 80, 100);
    [button1 setTitle:@"Continue downloading" forState:UIControlStateNormal];
    [button1 addTarget:self action:@selector(button3) forControlEvents:UIControlEventTouchUpInside];
    button1.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:button1];
    
    
    
    showLabel = [[UILabel alloc] init];
    showLabel.frame = CGRectMake(0, 200, self.view.frame.size.width, 40);
    showLabel.textAlignment = NSTextAlignmentCenter;
    showLabel.textColor = [UIColor redColor];
    [self.view addSubview:showLabel];
    
    
 
     NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:URL]];
    
    
    task = [manager dataTaskWithRequest:request uploadProgress:NULL downloadProgress:^(NSProgress * _Nonnull downloadProgress) {
    
        fileTotalSize = downloadProgress.totalUnitCount;
        
    } completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
         NSLog(@"%ld ======     ", fileTotalSize);
    }];

    
    [manager setDataTaskDidReceiveResponseBlock:^NSURLSessionResponseDisposition(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSURLResponse * _Nonnull response) {
        
        NSFileManager *fma = [NSFileManager defaultManager];
        
        if (![fma fileExistsAtPath:FILEPATH]) {
            // If no files are downloaded, create a file. If you have downloaded files, you don't need to recreate them (or you will overwrite the previous files)
           
          BOOL b = [fma createDirectoryAtPath:FILEPATH withIntermediateDirectories:YES attributes:nil error:NULL];
            if (b) {
                NSLog(@"=============");
            }else{
                 NSLog(@"===###############=====");
            }
            
            
            
            if (![fma fileExistsAtPath:FILEPATHName]) {
                
                b =  [fma createFileAtPath:FILEPATHName contents:nil attributes:nil];
                
                if (b) {
                    NSLog(@"=============");
                }else{
                    NSLog(@"===###############=====");
                }
            }
          
        }
        
        fileHandle = [NSFileHandle fileHandleForWritingAtPath:FILEPATHName];
        
        
        
        return NSURLSessionResponseAllow;
    }];
    
    [manager setDataTaskDidReceiveDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSData * _Nonnull data) {
        
        long long l = [fileHandle seekToEndOfFile];
        [fileHandle writeData:data];
        fileCompleteSize += data.length;
        
        
        NSLog(@"%lld",l);

        
        NSOperationQueue* mainQueue = [NSOperationQueue mainQueue];
        [mainQueue addOperationWithBlock:^{
          
            showLabel.text = [NSString stringWithFormat:@"%ld / %ld",fileCompleteSize,fileTotalSize];
        }];
        
        
    }];
    
   
    
    
    
    
   
    
   
    
    
    
    
    
}


-(void)button1{
    
     [task resume];
}

-(void)button2{
    [task suspend];
}
-(void)button3{
    
//     [task resume];
    [self contiuneAction];
}


-(void)contiuneAction{
    
    if (task) {
        task = nil;
    }
    
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:URL]];
    NSString *range = [NSString stringWithFormat:@"bytes=%zd-", fileCompleteSize];
    [request setValue:range forHTTPHeaderField:@"Range"];
    
    
    
    
    
    task = [manager dataTaskWithRequest:request uploadProgress:NULL downloadProgress:^(NSProgress * _Nonnull downloadProgress) {
        
        fileTotalSize = downloadProgress.totalUnitCount;
        
    } completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
        NSLog(@"%ld ======     ", fileTotalSize);
    }];
    
    
    [manager setDataTaskDidReceiveResponseBlock:^NSURLSessionResponseDisposition(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSURLResponse * _Nonnull response) {
        
        NSFileManager *fma = [NSFileManager defaultManager];
        
        BOOL b = [fma createDirectoryAtPath:FILEPATH withIntermediateDirectories:YES attributes:nil error:NULL];
        if (b) {
            NSLog(@"=============");
        }else{
            NSLog(@"===###############=====");
        }
        
        
        
        if (![fma fileExistsAtPath:FILEPATHName]) {
            
            b =  [fma createFileAtPath:FILEPATHName contents:nil attributes:nil];
            
            if (b) {
                NSLog(@"=============");
            }else{
                NSLog(@"===###############=====");
            }
        }

        
        
         fileHandle = [NSFileHandle fileHandleForWritingAtPath:FILEPATHName];
        
        return NSURLSessionResponseAllow;
    }];
    
    [manager setDataTaskDidReceiveDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSData * _Nonnull data) {
        
        long long l = [fileHandle seekToEndOfFile];
        [fileHandle writeData:data];
        fileCompleteSize += data.length;
        
        
        NSLog(@"%lld",l);
        
        NSOperationQueue* mainQueue = [NSOperationQueue mainQueue];
        [mainQueue addOperationWithBlock:^{
            
            showLabel.text = [NSString stringWithFormat:@"%ld / %ld",fileCompleteSize,fileTotalSize];
        }];
        
        
    }];
    
    [task resume];
    

}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end


Then, take a screenshot...




[task resume] means to continue downloading, so I suggest that you suspend downloading, then go to the WC and squat for ten minutes, and let him continue downloading to see if it's okay, then you will understand why I did it.





Oh, yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah.  
















Keywords: Session simulator github xcode

Added by Zamees on Wed, 19 Jun 2019 22:58:24 +0300