iOS 服务器文件有修改才进行下载

当要下载的文件会定期修改,而且比较大时,可以在文件有修改的时候,才进行下载。


有两种方式

一、需要服务器支持304状态码(推荐

请求中带上 If-Modified-Since 字段,如果在这个时间后,文件有修改,则返回200状态码,以及文件内容。如果文件没有修改,则返回304状态码,文件内容不会返回

+(void)downloadFileIfUpdatedWithLocalPath:(NSString*)path url:(NSString*)urlStr
{
    if(path.length == 0 || urlStr.length == 0)
        return;
    
    // 保存文件最后修改时间的Key
    NSString *lastModifyKey = KeyLastModify([urlStr MD5]);
    // 获取上次得到的文件最后修改时间
    NSString *lastModifyLocal = [[NSUserDefaults standardUserDefaults] objectForKey:lastModifyKey];
    
    NSURL *url = [NSURL URLWithString:urlStr];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"GET"];
    [request setValue:lastModifyLocal forHTTPHeaderField:@"If-Modified-Since"];
    
    NSURLSessionDownloadTask *task = [[NSURLSession sharedSession] downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        if(!error)
        {
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            
            if(httpResponse.statusCode == 200)
            {
                NSFileManager *fileManager = [NSFileManager defaultManager];
                
                NSString *fileDir = [path stringByDeletingLastPathComponent];
                if(![fileManager fileExistsAtPath:fileDir])
                {
                    // 创建目录
                    [fileManager createDirectoryAtPath:fileDir withIntermediateDirectories:YES attributes:nil error:nil];
                }
                
                NSData *fileData = [NSData dataWithContentsOfURL:location];
                if ([fileData writeToFile:path atomically:YES])
                {
                    // 存储文件的最后修改时间
                    NSString *lastModifyServer = [[httpResponse allHeaderFields] objectForKey:@"Last-Modified"];
                    [[NSUserDefaults standardUserDefaults] setObject:lastModifyServer forKey:lastModifyKey];
                }
                
            }
            else if(httpResponse.statusCode == 304)
            {
                NSLog(@"无需更新%@",[path lastPathComponent]);
            }
            
        }
        
    }];
    
    [task resume];
}


二、不需要服务器支持304状态码

1、通过HEAD请求获取文件的最后修改时间

2、与本地存储的文件最后修改时间进行比较

3、如果有更新,则直接请求文件

下面方法需要放到异步队列中执行,否则会阻塞主线程

+(void)downloadFileIfUpdatedWithLocalPath:(NSString*)path url:(NSString*)urlStr
{
    BOOL download = NO;

    NSURL *url = [NSURL URLWithString:urlStr];

    NSDate *lastModifiedLocal = nil;
    NSDate *lastModifiedServer = nil;

    // 询问服务器是否有修改
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"HEAD"];
    NSHTTPURLResponse *response;
    [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];
    if ([response respondsToSelector:@selector(allHeaderFields)]) {
        NSString *lastModifiedString = [[response allHeaderFields] objectForKey:@"Last-Modified"];

        NSDateFormatter *df = [[NSDateFormatter alloc] init];
        df.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'";
        df.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
        df.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
        lastModifiedServer = [df dateFromString:lastModifiedString];
    }

    // 查看本地存储
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:path]) {
        NSError *error = nil;
        NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:path error:&error];
        lastModifiedLocal = [fileAttributes fileModificationDate];
    }

    if (!lastModifiedLocal || [lastModifiedLocal laterDate:lastModifiedServer] == lastModifiedServer) {
        download = YES;
    }

    if(download)
    {
        NSData *data = [NSData dataWithContentsOfURL:url];
        if (data)
        {
            NSString *dirPath = [path stringByDeletingLastPathComponent];
            NSError *error = nil;
            if(![fileManager fileExistsAtPath:dirPath])
            {
                [fileManager createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:&error];
            }

            if ([data writeToFile:path atomically:YES])
            {
                NSLog(@"Downloaded file saved to: %@", path);
            }

            if (lastModifiedServer)
            {
                NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:lastModifiedServer forKey:NSFileModificationDate];

                if ([fileManager setAttributes:fileAttributes ofItemAtPath:path error:&error]) {
                    NSLog(@"File modification date updated");
                }
                if (error) {
                    NSLog(@"Error setting file attributes for: %@ - %@", path, [error localizedDescription]);
                }
            }
        }
    }

}


比较

方式一:

1、不管文件是否需要更新,都只有一次请求;

2、最后修改时间的比较,都由服务器处理,App无需关心时间的格式


方式二:

1、文件不需要更新时,只有一次请求。文件需要更新时,一共有两次请求;

2、最后修改时间由App比较,需要关心时间格式。一旦时间格式改变,就会有问题




你可能感兴趣的:(iOS,iOS,LastModified,Download,File)