DFPlayerRequestManager.m 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. //
  2. // DFPlayerRequestManager.m
  3. // DFPlayer
  4. //
  5. // Created by ihoudf on 2017/7/31.
  6. // Copyright © 2017年 ihoudf. All rights reserved.
  7. //
  8. #import "DFPlayerRequestManager.h"
  9. #import "DFPlayerTool.h"
  10. #import "DFPlayerFileManager.h"
  11. @interface DFPlayerRequestModel : NSObject<NSCoding>
  12. @property (nonatomic, copy) NSString *last_modified;
  13. @property (nonatomic, copy) NSString *ETag;
  14. @end
  15. @implementation DFPlayerRequestModel
  16. - (void)encodeWithCoder:(NSCoder *)aCoder{
  17. [aCoder encodeObject:self.last_modified forKey:@"last_modified"];
  18. [aCoder encodeObject:self.ETag forKey:@"ETag"];
  19. }
  20. - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder{
  21. self = [super init];
  22. if (self) {
  23. self.last_modified = [aDecoder decodeObjectForKey:@"last_modified"];
  24. self.ETag = [aDecoder decodeObjectForKey:@"ETag"];
  25. }
  26. return self;
  27. }
  28. - (void)setValue:(id)value forUndefinedKey:(NSString *)key{}
  29. @end
  30. @interface DFPlayerRequestManager()<NSURLSessionDataDelegate>
  31. @property (nonatomic, strong) NSMutableURLRequest *request;
  32. @property (nonatomic, strong) NSURLSession *session;
  33. @property (nonatomic, strong) NSURLSessionDataTask *dataTask;
  34. @property (nonatomic, strong) NSURL *requestUrl;
  35. @property (nonatomic, strong) NSMutableArray *archiverArray;
  36. @property (nonatomic, strong) NSOperationQueue *operationQueue;
  37. @property (nonatomic, assign) BOOL isNewAudio;
  38. @end
  39. @implementation DFPlayerRequestManager
  40. + (instancetype)requestWithUrl:(NSURL *)url{
  41. return [[self alloc] initWithUrl:url];
  42. }
  43. - (instancetype)initWithUrl:(NSURL *)url{
  44. self = [super init];
  45. if (self) {
  46. [DFPlayerTool startMonitoringNetworkStatus:^(DFPlayerNetworkStatus networkStatus) {
  47. if (!self.isNewAudio) {
  48. if (networkStatus != DFPlayerNetworkStatusUnknown ||
  49. networkStatus != DFPlayerNetworkStatusNotReachable) {
  50. self.requestOffset = self.cacheLength;
  51. [self resumeRequestStart];
  52. }
  53. }
  54. }];
  55. [DFPlayerFileManager df_createTempFile];
  56. self.requestUrl = [DFPlayerTool originalURL:url];
  57. self.operationQueue = [[NSOperationQueue alloc] init];
  58. self.operationQueue.maxConcurrentOperationCount = 1;
  59. }
  60. return self;
  61. }
  62. - (void)requestStart{
  63. __block DFPlayerRequestModel *model = [[DFPlayerRequestModel alloc] init];
  64. if (self.isHaveCache) {//安全性判断。如果沙盒存在缓存文件,再去发起校验。沙盒没有,直接下载缓存
  65. if (self.isObserveFileModifiedTime) {
  66. NSMutableDictionary *dic = [DFPlayerArchiverManager df_hasArchivedFileDictionary];
  67. [dic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
  68. if ([key isEqualToString:self.requestUrl.absoluteString]) {
  69. model = (DFPlayerRequestModel *)obj;
  70. *stop = YES;
  71. }
  72. }];
  73. }
  74. }
  75. self.isNewAudio = YES;
  76. //直接请求源端数据
  77. self.request = [NSMutableURLRequest requestWithURL:self.requestUrl
  78. cachePolicy:(NSURLRequestReloadIgnoringCacheData)
  79. timeoutInterval:10.0];
  80. if (model.ETag) {
  81. [self.request addValue:model.ETag forHTTPHeaderField:@"If-None-Match"];
  82. }
  83. if (model.last_modified) {
  84. [self.request addValue:model.last_modified forHTTPHeaderField:@"If-Modified-Since"];
  85. }
  86. [self requestDataTask];
  87. }
  88. - (void)resumeRequestStart{
  89. //直接请求源端数据
  90. self.request = [NSMutableURLRequest requestWithURL:self.requestUrl
  91. cachePolicy:(NSURLRequestReloadIgnoringCacheData)
  92. timeoutInterval:10.0];
  93. if (self.requestOffset > 0) {
  94. NSString *value = [NSString stringWithFormat:@"bytes=%ld-%ld", (long)self.requestOffset,(long)self.fileLength];
  95. [self.request addValue:value forHTTPHeaderField:@"Range"];
  96. }
  97. [self requestDataTask];
  98. }
  99. - (void)requestDataTask{
  100. NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
  101. self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:self.operationQueue];
  102. self.dataTask = [self.session dataTaskWithRequest:self.request];
  103. [self.dataTask resume];
  104. }
  105. - (void)setCancel:(BOOL)cancel {
  106. _cancel = cancel;
  107. [self.dataTask cancel];
  108. [self.session invalidateAndCancel];
  109. }
  110. #pragma mark - NSURLSessionDataDelegate
  111. //服务器响应
  112. - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
  113. if (_cancel) {
  114. return;
  115. }
  116. completionHandler(NSURLSessionResponseAllow);
  117. NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
  118. self.isNewAudio = NO;
  119. NSInteger statusCode = httpResponse.statusCode;
  120. if (statusCode == 200) {
  121. NSString *contentLength = httpResponse.allHeaderFields[@"Content-Length"];
  122. self.fileLength = (long)[contentLength integerValue] > 0 ? (long)[contentLength integerValue] : (long)[response expectedContentLength];
  123. DFPlayerRequestModel *model = [DFPlayerRequestModel new];
  124. model.last_modified = httpResponse.allHeaderFields[@"Last-Modified"];
  125. model.ETag = httpResponse.allHeaderFields[@"Etag"];
  126. [DFPlayerArchiverManager df_archiveValue:model forKey:self.requestUrl.absoluteString];
  127. //如果没归档成功 如果本地有缓存则还是播放网络文件
  128. }else if(statusCode == 206){//带有Range请求头的返回
  129. }else{
  130. _cancel = YES;
  131. }
  132. if (self.delegate && [self.delegate respondsToSelector:@selector(requestManagerDidReceiveResponseWithStatusCode:)]) {
  133. [self.delegate requestManagerDidReceiveResponseWithStatusCode:statusCode];
  134. }
  135. }
  136. //服务器返回数据 可能会调用多次
  137. - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
  138. if (_cancel){
  139. return;
  140. }
  141. self.cacheLength += data.length;
  142. [DFPlayerFileManager df_writeDataToAudioFileTempPathWithData:data];
  143. if (self.delegate && [self.delegate respondsToSelector:@selector(requestManagerDidReceiveData)]) {
  144. [self.delegate requestManagerDidReceiveData];
  145. }
  146. }
  147. //请求完成会调用该方法,请求失败则error有值
  148. - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
  149. if (_cancel) {
  150. return;
  151. }
  152. if (error) {
  153. if (self.delegate && [self.delegate respondsToSelector:@selector(requestManagerDidCompleteWithError:)]) {
  154. [self.delegate requestManagerDidCompleteWithError:error.code];
  155. }
  156. }else {
  157. self.isNewAudio = YES;
  158. //可以缓存则保存文件
  159. BOOL success = [DFPlayerFileManager df_moveAudioFileFromTempPathToCachePath:self.requestUrl];
  160. if (self.delegate && [self.delegate respondsToSelector:@selector(requestManagerIsCached:)]) {
  161. [self.delegate requestManagerIsCached:success];
  162. }
  163. }
  164. }
  165. @end