diff --git a/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataReader.m b/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataReader.m index c83fd147..b23aae56 100644 --- a/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataReader.m +++ b/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataReader.m @@ -12,6 +12,7 @@ #import "KTVHCDataUnitPool.h" #import "KTVHCDataCallback.h" #import "KTVHCLog.h" +#import "KTVHCDataStorage.h" @interface KTVHCDataReader () @@ -145,24 +146,36 @@ - (void)prepareSourceManager }]; long long offset = self.request.range.start; long long length = KTVHCRangeGetLength(self.request.range); + long long chunkSize = 0; + if ([KTVHCDataStorage storage].requestHeaderRangeLength) { + chunkSize = [KTVHCDataStorage storage].requestHeaderRangeLength(self.request.URL, self.unit.totalLength); + } for (KTVHCDataFileSource *obj in fileSources) { long long delta = obj.range.start + obj.readRange.start - offset; if (delta > 0) { - KTVHCRange range = KTVHCMakeRange(offset, offset + delta - 1); - KTVHCDataRequest *request = [self.request newRequestWithRange:range]; - KTVHCDataNetworkSource *source = [[KTVHCDataNetworkSource alloc] initWithRequest:request]; - [networkSources addObject:source]; + if (chunkSize > 0) { + // 使用公共方法处理分片下载 + [self addNetworkSourcesWithOffset:offset length:delta chunkSize:chunkSize toArray:networkSources]; + }else { + // 单个网络源的情况 + [self addSingleNetworkSourceWithStart:offset end:offset + delta - 1 toArray:networkSources]; + } offset += delta; length -= delta; } offset += KTVHCRangeGetLength(obj.readRange); length -= KTVHCRangeGetLength(obj.readRange); } + + // 处理剩余需要下载的部分 if (length > 0) { - KTVHCRange range = KTVHCMakeRange(offset, self.request.range.end); - KTVHCDataRequest *request = [self.request newRequestWithRange:range]; - KTVHCDataNetworkSource *source = [[KTVHCDataNetworkSource alloc] initWithRequest:request]; - [networkSources addObject:source]; + if (chunkSize > 0) { + // 使用公共方法处理分片下载 + [self addNetworkSourcesWithOffset:offset length:length chunkSize:chunkSize toArray:networkSources]; + } else { + // 单个网络源的情况 + [self addSingleNetworkSourceWithStart:offset end:self.request.range.end toArray:networkSources]; + } } NSMutableArray> *sources = [NSMutableArray array]; [sources addObjectsFromArray:fileSources]; @@ -265,4 +278,41 @@ - (void)unlock [self.coreLock unlock]; } +#pragma mark - Private Methods + +// 添加单个网络源 +- (void)addSingleNetworkSourceWithStart:(long long)start + end:(long long)end + toArray:(NSMutableArray *)networkSources +{ + KTVHCRange range = KTVHCMakeRange(start, end); + KTVHCDataRequest *request = [self.request newRequestWithRange:range]; + KTVHCDataNetworkSource *source = [[KTVHCDataNetworkSource alloc] initWithRequest:request]; + [networkSources addObject:source]; +} + +// 添加分片网络源 +- (void)addNetworkSourcesWithOffset:(long long)offset + length:(long long)length + chunkSize:(long long)chunkSize + toArray:(NSMutableArray *)networkSources +{ + long long remainingLength = length; + long long currentOffset = offset; + while (remainingLength > 0) { + // 计算当前分片的大小 + long long chunkLength = MIN(remainingLength, chunkSize); + // 确保最后一个分片的结束位置不超过原始请求范围 + long long endOffset = MIN(currentOffset + chunkLength - 1, self.request.range.end); + + KTVHCRange chunkRange = KTVHCMakeRange(currentOffset, endOffset); + KTVHCDataRequest *request = [self.request newRequestWithRange:chunkRange]; + KTVHCDataNetworkSource *source = [[KTVHCDataNetworkSource alloc] initWithRequest:request]; + [networkSources addObject:source]; + + currentOffset += chunkLength; + remainingLength -= chunkLength; + } +} + @end diff --git a/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataStorage.h b/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataStorage.h index 1618a574..df647e03 100644 --- a/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataStorage.h +++ b/KTVHTTPCache/Classes/KTVHCDataStorage/KTVHCDataStorage.h @@ -53,4 +53,6 @@ - (void)deleteCacheWithURL:(NSURL *)URL; - (void)deleteAllCaches; +@property (nonatomic, copy) long long (^requestHeaderRangeLength)(NSURL *URL, long long totalLength); + @end diff --git a/KTVHTTPCache/KTVHTTPCache.h b/KTVHTTPCache/KTVHTTPCache.h index 3f5f7de3..a05f0f95 100644 --- a/KTVHTTPCache/KTVHTTPCache.h +++ b/KTVHTTPCache/KTVHTTPCache.h @@ -266,6 +266,14 @@ FOUNDATION_EXPORT const unsigned char KTVHTTPCacheVersionString[]; */ + (void)downloadSetUnacceptableContentTypeDisposer:(BOOL(^)(NSURL *URL, NSString *contentType))unacceptableContentTypeDisposer; +/** + * 设置下载文件 request range 分片长度 + * 解决 AVPlayer 播放器频繁取消再发起request请求,http range 区间有重叠,阿里云服务器流量统计过大问题。 + * + * @param requestHeaderRangeLength : 分片参数 + */ ++ (void)downloadSetRequestHeaderRangeLength:(long long(^)(NSURL *URL, long long totalLength))requestHeaderRangeLength; + /** * Log * diff --git a/KTVHTTPCache/KTVHTTPCache.m b/KTVHTTPCache/KTVHTTPCache.m index 20248dab..675b3552 100644 --- a/KTVHTTPCache/KTVHTTPCache.m +++ b/KTVHTTPCache/KTVHTTPCache.m @@ -153,6 +153,10 @@ + (void)downloadSetUnacceptableContentTypeDisposer:(BOOL(^)(NSURL *URL, NSString [KTVHCDownload download].unacceptableContentTypeDisposer = unacceptableContentTypeDisposer; } ++ (void)downloadSetRequestHeaderRangeLength:(long long(^)(NSURL *URL, long long totalLength))requestHeaderRangeLength{ + [KTVHCDataStorage storage].requestHeaderRangeLength = requestHeaderRangeLength; +} + #pragma mark - Log + (void)logAddLog:(NSString *)log diff --git a/demo/KTVHTTPCacheDemo/SGMediaViewController/SGMediaViewController.m b/demo/KTVHTTPCacheDemo/SGMediaViewController/SGMediaViewController.m index c5f2bcb6..5e49cb29 100644 --- a/demo/KTVHTTPCacheDemo/SGMediaViewController/SGMediaViewController.m +++ b/demo/KTVHTTPCacheDemo/SGMediaViewController/SGMediaViewController.m @@ -50,6 +50,14 @@ - (void)setupHTTPCache NSLog(@"Unsupport Content-Type Filter reviced URL : %@, %@", URL, contentType); return NO; }]; + + // 外部根据连接或者自己的规则设置请求分片大小,未设置block还是走播放器请求的request http range,如果设置分片大小, + // 播放器请求http range超过限制会内部分割成多个request串行请求数据 + /* + [KTVHTTPCache downloadSetRequestHeaderRangeLength:^long long(NSURL *URL, long long totalLength) { + return 2 * 1000 * 1000; + }]; + */ } - (void)setupItems