iOS NSURLSessionDownloadTask 报错 Invalid resume data for background download. Bac
程序员文章站
2024-01-06 20:50:28
错误: Invalid resume data for background download. Background downloads must use http or htt...
错误: Invalid resume data for background download. Background downloads must use http or https and must download to an accessible file.
网上好多说这个错误在ios10中出现,如果调试的时候,点暂停下载,再重新发布到手机上,再点击开始下载,也会有这个错误。
解决办法:自定义一个NSURLSession分类,在ios10代替- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;
NSURLSession+TYCorrectedResumeData.h
#import@interface NSURLSession (TYCorrectedResumeData) - (NSURLSessionDownloadTask *)downloadTaskWithCorrectResumeData:(NSData *)resumeData; @end
NSURLSession+TYCorrectedResumeData.m
// // NSURLSession+TYCorrectedResumeData.m // TYDownloadManagerDemo // // Created by tanyang on 2016/10/7. // Copyright © 2016年 tany. All rights reserved. // #import "NSURLSession+TYCorrectedResumeData.h" #import#define IS_IOS10ORLATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10) @implementation NSURLSession (TYCorrectedResumeData) - (NSURLSessionDownloadTask *)downloadTaskWithCorrectResumeData:(NSData *)resumeData { NSString *kResumeCurrentRequest = @"NSURLSessionResumeCurrentRequest"; NSString *kResumeOriginalRequest = @"NSURLSessionResumeOriginalRequest"; NSData *cData = correctResumeData(resumeData); cData = cData?cData:resumeData; NSURLSessionDownloadTask *task = [self downloadTaskWithResumeData:cData]; NSMutableDictionary *resumeDic = getResumeDictionary(cData); if (resumeDic) { if (task.originalRequest == nil) { NSData *originalReqData = resumeDic[kResumeOriginalRequest]; NSURLRequest *originalRequest = [NSKeyedUnarchiver unarchiveObjectWithData:originalReqData ]; if (originalRequest) { [task setValue:originalRequest forKey:@"originalRequest"]; } } if (task.currentRequest == nil) { NSData *currentReqData = resumeDic[kResumeCurrentRequest]; NSURLRequest *currentRequest = [NSKeyedUnarchiver unarchiveObjectWithData:currentReqData]; if (currentRequest) { [task setValue:currentRequest forKey:@"currentRequest"]; } } } return task; } #pragma mark- private NSData * correctRequestData(NSData *data) { if (!data) { return nil; } // return the same data if it's correct if ([NSKeyedUnarchiver unarchiveObjectWithData:data] != nil) { return data; } NSMutableDictionary *archive = [[NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:nil error:nil] mutableCopy]; if (!archive) { return nil; } NSInteger k = 0; id objectss = archive[@"$objects"]; while ([objectss[1] objectForKey:[NSString stringWithFormat:@"$%ld",k]] != nil) { k += 1; } NSInteger i = 0; while ([archive[@"$objects"][1] objectForKey:[NSString stringWithFormat:@"__nsurlrequest_proto_prop_obj_%ld",i]] != nil) { NSMutableArray *arr = archive[@"$objects"]; NSMutableDictionary *dic = arr[1]; id obj = [dic objectForKey:[NSString stringWithFormat:@"__nsurlrequest_proto_prop_obj_%ld",i]]; if (obj) { [dic setValue:obj forKey:[NSString stringWithFormat:@"$%ld",i+k]]; [dic removeObjectForKey:[NSString stringWithFormat:@"__nsurlrequest_proto_prop_obj_%ld",i]]; [arr replaceObjectAtIndex:1 withObject:dic]; archive[@"$objects"] = arr; } i++; } if ([archive[@"$objects"][1] objectForKey:@"__nsurlrequest_proto_props"] != nil) { NSMutableArray *arr = archive[@"$objects"]; NSMutableDictionary *dic = arr[1]; id obj = [dic objectForKey:@"__nsurlrequest_proto_props"]; if (obj) { [dic setValue:obj forKey:[NSString stringWithFormat:@"$%ld",i+k]]; [dic removeObjectForKey:@"__nsurlrequest_proto_props"]; [arr replaceObjectAtIndex:1 withObject:dic]; archive[@"$objects"] = arr; } } // Rectify weird "NSKeyedArchiveRootObjectKey" top key to NSKeyedArchiveRootObjectKey = "root" if ([archive[@"$top"] objectForKey:@"NSKeyedArchiveRootObjectKey"] != nil) { [archive[@"$top"] setObject:archive[@"$top"][@"NSKeyedArchiveRootObjectKey"] forKey: NSKeyedArchiveRootObjectKey]; [archive[@"$top"] removeObjectForKey:@"NSKeyedArchiveRootObjectKey"]; } // Reencode archived object NSData *result = [NSPropertyListSerialization dataWithPropertyList:archive format:NSPropertyListBinaryFormat_v1_0 options:0 error:nil]; return result; } NSMutableDictionary *getResumeDictionary(NSData *data) { NSMutableDictionary *iresumeDictionary = nil; if (IS_IOS10ORLATER) { id root = nil; id keyedUnarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; @try { root = [keyedUnarchiver decodeTopLevelObjectForKey:@"NSKeyedArchiveRootObjectKey" error:nil]; if (root == nil) { root = [keyedUnarchiver decodeTopLevelObjectForKey:NSKeyedArchiveRootObjectKey error:nil]; } } @catch(NSException *exception) { } [keyedUnarchiver finishDecoding]; iresumeDictionary = [root mutableCopy]; } if (iresumeDictionary == nil) { iresumeDictionary = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:nil error:nil]; } return iresumeDictionary; } NSData *correctResumeData(NSData *data) { NSString *kResumeCurrentRequest = @"NSURLSessionResumeCurrentRequest"; NSString *kResumeOriginalRequest = @"NSURLSessionResumeOriginalRequest"; if (data == nil) { return nil; } NSMutableDictionary *resumeDictionary = getResumeDictionary(data); if (resumeDictionary == nil) { return nil; } resumeDictionary[kResumeCurrentRequest] = correctRequestData(resumeDictionary[kResumeCurrentRequest]); resumeDictionary[kResumeOriginalRequest] = correctRequestData(resumeDictionary[kResumeOriginalRequest]); NSData *result = [NSPropertyListSerialization dataWithPropertyList:resumeDictionary format:NSPropertyListXMLFormat_v1_0 options:0 error:nil]; return result; } @end