解决了语音上传到问题,接下来要解决下载播放问题

This commit is contained in:
joywayer
2025-06-15 12:36:47 +08:00
parent bba3ed1cb4
commit c11fc62bf1
513 changed files with 31197 additions and 2969 deletions

View File

@@ -0,0 +1,323 @@
//
// QNHttpRequest+SingleRequestRetry.m
// QiniuSDK
//
// Created by yangsen on 2020/4/29.
// Copyright © 2020 Qiniu. All rights reserved.
//
#import "QNDefine.h"
#import "QNAsyncRun.h"
#import "QNVersion.h"
#import "QNUtils.h"
#import "QNLogUtil.h"
#import "QNHttpSingleRequest.h"
#import "QNConfiguration.h"
#import "QNUploadOption.h"
#import "QNUpToken.h"
#import "QNResponseInfo.h"
#import "QNNetworkStatusManager.h"
#import "QNRequestClient.h"
#import "QNUploadRequestState.h"
#import "QNConnectChecker.h"
#import "QNDnsPrefetch.h"
#import "QNReportItem.h"
#import "QNCFHttpClient.h"
#import "QNUploadSystemClient.h"
#import "NSURLRequest+QNRequest.h"
@interface QNHttpSingleRequest()
@property(nonatomic, assign)int currentRetryTime;
@property(nonatomic, strong)QNConfiguration *config;
@property(nonatomic, strong)QNUploadOption *uploadOption;
@property(nonatomic, strong)QNUpToken *token;
@property(nonatomic, strong)QNUploadRequestInfo *requestInfo;
@property(nonatomic, strong)QNUploadRequestState *requestState;
@property(nonatomic, strong)NSMutableArray <QNUploadSingleRequestMetrics *> *requestMetricsList;
@property(nonatomic, strong)id <QNRequestClient> client;
@end
@implementation QNHttpSingleRequest
- (instancetype)initWithConfig:(QNConfiguration *)config
uploadOption:(QNUploadOption *)uploadOption
token:(QNUpToken *)token
requestInfo:(QNUploadRequestInfo *)requestInfo
requestState:(QNUploadRequestState *)requestState{
if (self = [super init]) {
_config = config;
_uploadOption = uploadOption;
_token = token;
_requestInfo = requestInfo;
_requestState = requestState;
_currentRetryTime = 0;
}
return self;
}
- (void)request:(NSURLRequest *)request
server:(id <QNUploadServer>)server
shouldRetry:(BOOL(^)(QNResponseInfo *responseInfo, NSDictionary *response))shouldRetry
progress:(void(^)(long long totalBytesWritten, long long totalBytesExpectedToWrite))progress
complete:(QNSingleRequestCompleteHandler)complete{
_currentRetryTime = 0;
_requestMetricsList = [NSMutableArray array];
[self retryRequest:request server:server shouldRetry:shouldRetry progress:progress complete:complete];
}
- (void)retryRequest:(NSURLRequest *)request
server:(id <QNUploadServer>)server
shouldRetry:(BOOL(^)(QNResponseInfo *responseInfo, NSDictionary *response))shouldRetry
progress:(void(^)(long long totalBytesWritten, long long totalBytesExpectedToWrite))progress
complete:(QNSingleRequestCompleteHandler)complete{
if (kQNIsHttp3(server.httpVersion)) {
self.client = [[QNUploadSystemClient alloc] init];
} else {
if ([self shouldUseCFClient:request server:server]) {
self.client = [[QNCFHttpClient alloc] init];
} else {
self.client = [[QNUploadSystemClient alloc] init];
}
}
kQNWeakSelf;
BOOL (^checkCancelHandler)(void) = ^{
kQNStrongSelf;
BOOL isCancelled = self.requestState.isUserCancel;
if (!isCancelled && self.uploadOption.cancellationSignal) {
isCancelled = self.uploadOption.cancellationSignal();
}
return isCancelled;
};
QNLogInfo(@"key:%@ retry:%d url:%@", self.requestInfo.key, self.currentRetryTime, request.URL);
[self.client request:request server:server connectionProxy:self.config.proxy progress:^(long long totalBytesWritten, long long totalBytesExpectedToWrite) {
kQNStrongSelf;
if (progress) {
progress(totalBytesWritten, totalBytesExpectedToWrite);
}
if (checkCancelHandler()) {
self.requestState.isUserCancel = YES;
[self.client cancel];
}
} complete:^(NSURLResponse *response, QNUploadSingleRequestMetrics *metrics, NSData * responseData, NSError * error) {
kQNStrongSelf;
if (metrics) {
[self.requestMetricsList addObject:metrics];
}
QNResponseInfo *responseInfo = nil;
if (checkCancelHandler()) {
responseInfo = [QNResponseInfo cancelResponse];
[self reportRequest:responseInfo server:server requestMetrics:metrics];
[self complete:responseInfo server:server response:nil requestMetrics:metrics complete:complete];
return;
}
NSDictionary *responseDic = nil;
if (responseData) {
responseDic = [NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingMutableLeaves
error:nil];
}
responseInfo = [[QNResponseInfo alloc] initWithResponseInfoHost:request.qn_domain
response:(NSHTTPURLResponse *)response
body:responseData
error:error];
BOOL isSafeDnsSource = kQNIsDnsSourceCustom(server.source) || kQNIsDnsSourceDoh(server.source) || kQNIsDnsSourceDnsPod(server.source);
BOOL hijacked = responseInfo.isNotQiniu && !isSafeDnsSource;
if (hijacked) {
metrics.hijacked = kQNMetricsRequestHijacked;
NSError *err = nil;
metrics.syncDnsSource = [kQNDnsPrefetch prefetchHostBySafeDns:server.host error:&err];
metrics.syncDnsError = err;
}
if (!hijacked && [self shouldCheckConnect:responseInfo]) {
//
QNUploadSingleRequestMetrics *connectCheckMetrics = [QNConnectChecker check];
metrics.connectCheckMetrics = connectCheckMetrics;
if (![QNConnectChecker isConnected:connectCheckMetrics]) {
NSString *message = [NSString stringWithFormat:@"check origin statusCode:%d error:%@", responseInfo.statusCode, responseInfo.error];
responseInfo = [QNResponseInfo errorResponseInfo:NSURLErrorNotConnectedToInternet errorDesc:message];
} else if (!isSafeDnsSource) {
metrics.hijacked = kQNMetricsRequestMaybeHijacked;
NSError *err = nil;
[kQNDnsPrefetch prefetchHostBySafeDns:server.host error:&err];
metrics.syncDnsError = err;
}
}
[self reportRequest:responseInfo server:server requestMetrics:metrics];
QNLogInfo(@"key:%@ response:%@", self.requestInfo.key, responseInfo);
if (shouldRetry(responseInfo, responseDic)
&& self.currentRetryTime < self.config.retryMax
&& responseInfo.couldHostRetry) {
self.currentRetryTime += 1;
QNAsyncRunAfter(self.config.retryInterval, kQNBackgroundQueue, ^{
[self retryRequest:request server:server shouldRetry:shouldRetry progress:progress complete:complete];
});
} else {
[self complete:responseInfo server:server response:responseDic requestMetrics:metrics complete:complete];
}
}];
}
- (BOOL)shouldCheckConnect:(QNResponseInfo *)responseInfo {
if (!kQNGlobalConfiguration.connectCheckEnable || [kQNGlobalConfiguration.connectCheckURLStrings count] == 0) {
return NO;
}
return responseInfo.statusCode == kQNNetworkError ||
responseInfo.statusCode == kQNUnexpectedSysCallError || // CF
responseInfo.statusCode == NSURLErrorTimedOut /* NSURLErrorTimedOut */ ||
responseInfo.statusCode == -1003 /* NSURLErrorCannotFindHost */ ||
responseInfo.statusCode == -1004 /* NSURLErrorCannotConnectToHost */ ||
responseInfo.statusCode == -1005 /* NSURLErrorNetworkConnectionLost */ ||
responseInfo.statusCode == -1006 /* NSURLErrorDNSLookupFailed */ ||
responseInfo.statusCode == -1009 /* NSURLErrorNotConnectedToInternet */ ||
responseInfo.statusCode == -1200 /* NSURLErrorSecureConnectionFailed */ ||
responseInfo.statusCode == -1204 /* NSURLErrorServerCertificateNotYetValid */ ||
responseInfo.statusCode == -1205 /* NSURLErrorClientCertificateRejected */;
}
- (void)complete:(QNResponseInfo *)responseInfo
server:(id<QNUploadServer>)server
response:(NSDictionary *)response
requestMetrics:(QNUploadSingleRequestMetrics *)requestMetrics
complete:(QNSingleRequestCompleteHandler)complete {
[self updateHostNetworkStatus:responseInfo server:server requestMetrics:requestMetrics];
if (complete) {
complete(responseInfo, [self.requestMetricsList copy], response);
}
}
- (BOOL)shouldUseCFClient:(NSURLRequest *)request server:(id <QNUploadServer>)server {
if (request.qn_isHttps && server.host.length > 0 && server.ip.length > 0) {
return YES;
} else {
return NO;
}
}
//MARK:--
- (void)updateHostNetworkStatus:(QNResponseInfo *)responseInfo
server:(id <QNUploadServer>)server
requestMetrics:(QNUploadSingleRequestMetrics *)requestMetrics{
long long bytes = requestMetrics.bytesSend.longLongValue;
if (requestMetrics.startDate && requestMetrics.endDate && bytes >= 1024 * 1024) {
double duration = [requestMetrics.endDate timeIntervalSinceDate:requestMetrics.startDate] * 1000;
NSNumber *speed = [QNUtils calculateSpeed:bytes totalTime:duration];
if (speed) {
NSString *type = [QNNetworkStatusManager getNetworkStatusType:server.host ip:server.ip];
[kQNNetworkStatusManager updateNetworkStatus:type speed:(int)(speed.longValue / 1000)];
}
}
}
//MARK:-- quality
- (void)reportRequest:(QNResponseInfo *)info
server:(id <QNUploadServer>)server
requestMetrics:(QNUploadSingleRequestMetrics *)requestMetrics {
if (! [self.requestInfo shouldReportRequestLog]) {
return;
}
QNUploadSingleRequestMetrics *requestMetricsP = requestMetrics ?: [QNUploadSingleRequestMetrics emptyMetrics];
NSInteger currentTimestamp = [QNUtils currentTimestamp];
QNReportItem *item = [QNReportItem item];
[item setReportValue:QNReportLogTypeRequest forKey:QNReportRequestKeyLogType];
[item setReportValue:@(currentTimestamp/1000) forKey:QNReportRequestKeyUpTime];
[item setReportValue:info.requestReportStatusCode forKey:QNReportRequestKeyStatusCode];
[item setReportValue:info.reqId forKey:QNReportRequestKeyRequestId];
[item setReportValue:requestMetricsP.request.qn_domain forKey:QNReportRequestKeyHost];
[item setReportValue:requestMetricsP.remoteAddress forKey:QNReportRequestKeyRemoteIp];
[item setReportValue:requestMetricsP.remotePort forKey:QNReportRequestKeyPort];
[item setReportValue:self.requestInfo.bucket forKey:QNReportRequestKeyTargetBucket];
[item setReportValue:self.requestInfo.key forKey:QNReportRequestKeyTargetKey];
[item setReportValue:requestMetricsP.totalElapsedTime forKey:QNReportRequestKeyTotalElapsedTime];
[item setReportValue:requestMetricsP.totalDnsTime forKey:QNReportRequestKeyDnsElapsedTime];
[item setReportValue:requestMetricsP.totalConnectTime forKey:QNReportRequestKeyConnectElapsedTime];
[item setReportValue:requestMetricsP.totalSecureConnectTime forKey:QNReportRequestKeyTLSConnectElapsedTime];
[item setReportValue:requestMetricsP.totalRequestTime forKey:QNReportRequestKeyRequestElapsedTime];
[item setReportValue:requestMetricsP.totalWaitTime forKey:QNReportRequestKeyWaitElapsedTime];
[item setReportValue:requestMetricsP.totalWaitTime forKey:QNReportRequestKeyResponseElapsedTime];
[item setReportValue:requestMetricsP.totalResponseTime forKey:QNReportRequestKeyResponseElapsedTime];
[item setReportValue:self.requestInfo.fileOffset forKey:QNReportRequestKeyFileOffset];
[item setReportValue:requestMetricsP.bytesSend forKey:QNReportRequestKeyBytesSent];
[item setReportValue:requestMetricsP.totalBytes forKey:QNReportRequestKeyBytesTotal];
[item setReportValue:@([QNUtils getCurrentProcessID]) forKey:QNReportRequestKeyPid];
[item setReportValue:@([QNUtils getCurrentThreadID]) forKey:QNReportRequestKeyTid];
[item setReportValue:self.requestInfo.targetRegionId forKey:QNReportRequestKeyTargetRegionId];
[item setReportValue:self.requestInfo.currentRegionId forKey:QNReportRequestKeyCurrentRegionId];
[item setReportValue:info.requestReportErrorType forKey:QNReportRequestKeyErrorType];
NSString *errorDesc = info.requestReportErrorType ? info.message : nil;
[item setReportValue:errorDesc forKey:QNReportRequestKeyErrorDescription];
[item setReportValue:self.requestInfo.requestType forKey:QNReportRequestKeyUpType];
[item setReportValue:[QNUtils systemName] forKey:QNReportRequestKeyOsName];
[item setReportValue:[QNUtils systemVersion] forKey:QNReportRequestKeyOsVersion];
[item setReportValue:[QNUtils sdkLanguage] forKey:QNReportRequestKeySDKName];
[item setReportValue:[QNUtils sdkVersion] forKey:QNReportRequestKeySDKVersion];
[item setReportValue:@([QNUtils currentTimestamp]) forKey:QNReportRequestKeyClientTime];
[item setReportValue:[QNUtils getCurrentNetworkType] forKey:QNReportRequestKeyNetworkType];
[item setReportValue:[QNUtils getCurrentSignalStrength] forKey:QNReportRequestKeySignalStrength];
[item setReportValue:server.source forKey:QNReportRequestKeyPrefetchedDnsSource];
if (server.ipPrefetchedTime) {
NSInteger prefetchTime = currentTimestamp/1000 - [server.ipPrefetchedTime integerValue];
[item setReportValue:@(prefetchTime) forKey:QNReportRequestKeyPrefetchedBefore];
}
[item setReportValue:kQNDnsPrefetch.lastPrefetchedErrorMessage forKey:QNReportRequestKeyPrefetchedErrorMessage];
[item setReportValue:requestMetricsP.httpVersion forKey:QNReportRequestKeyHttpVersion];
if (!kQNGlobalConfiguration.connectCheckEnable) {
[item setReportValue:@"disable" forKey:QNReportRequestKeyNetworkMeasuring];
} else if (requestMetricsP.connectCheckMetrics) {
QNUploadSingleRequestMetrics *metrics = requestMetricsP.connectCheckMetrics;
NSString *connectCheckDuration = [NSString stringWithFormat:@"%.2lf", [metrics.totalElapsedTime doubleValue]];
NSString *connectCheckStatusCode = @"";
if (metrics.response) {
connectCheckStatusCode = [NSString stringWithFormat:@"%ld", (long)((NSHTTPURLResponse *)metrics.response).statusCode];
} else if (metrics.error) {
connectCheckStatusCode = [NSString stringWithFormat:@"%ld", (long)metrics.error.code];
}
NSString *networkMeasuring = [NSString stringWithFormat:@"duration:%@ status_code:%@",connectCheckDuration, connectCheckStatusCode];
[item setReportValue:networkMeasuring forKey:QNReportRequestKeyNetworkMeasuring];
}
//
[item setReportValue:requestMetricsP.hijacked forKey:QNReportRequestKeyHijacking];
[item setReportValue:requestMetricsP.syncDnsSource forKey:QNReportRequestKeyDnsSource];
[item setReportValue:[requestMetricsP.syncDnsError description] forKey:QNReportRequestKeyDnsErrorMessage];
//
if (info.isOK) {
[item setReportValue:requestMetricsP.perceptiveSpeed forKey:QNReportRequestKeyPerceptiveSpeed];
}
[item setReportValue:self.client.clientId forKey:QNReportRequestKeyHttpClient];
[kQNReporter reportItem:item token:self.token.token];
}
@end