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

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,322 @@
//
// QNUploadInfoV2.m
// QiniuSDK
//
// Created by yangsen on 2021/5/13.
// Copyright © 2021 Qiniu. All rights reserved.
//
#import "NSData+QNMD5.h"
#import "QNMutableArray.h"
#import "QNUploadInfoV2.h"
#define kTypeValue @"UploadInfoV2"
#define kMaxDataSize (1024 * 1024 * 1024)
@interface QNUploadInfoV2()
@property(nonatomic, assign)int dataSize;
@property(nonatomic, strong)QNMutableArray *dataList;
@property(nonatomic, assign)BOOL isEOF;
@property(nonatomic, strong, nullable)NSError *readError;
@end
@implementation QNUploadInfoV2
+ (instancetype)info:(id<QNUploadSource>)source
configuration:(nonnull QNConfiguration *)configuration {
QNUploadInfoV2 *info = [QNUploadInfoV2 info:source];
info.dataSize = MIN(configuration.chunkSize, kMaxDataSize);
info.dataList = [QNMutableArray array];
return info;
}
+ (instancetype)info:(id <QNUploadSource>)source
dictionary:(NSDictionary *)dictionary {
if (dictionary == nil) {
return nil;
}
int dataSize = [dictionary[@"dataSize"] intValue];
NSNumber *expireAt = dictionary[@"expireAt"];
NSString *uploadId = dictionary[@"uploadId"];
NSString *type = dictionary[kQNUploadInfoTypeKey];
if (expireAt == nil || ![expireAt isKindOfClass:[NSNumber class]] ||
uploadId == nil || ![uploadId isKindOfClass:[NSString class]] || uploadId.length == 0) {
return nil;
}
NSArray *dataInfoList = dictionary[@"dataList"];
QNMutableArray *dataList = [QNMutableArray array];
if ([dataInfoList isKindOfClass:[NSArray class]]) {
for (int i = 0; i < dataInfoList.count; i++) {
NSDictionary *dataInfo = dataInfoList[i];
if ([dataInfo isKindOfClass:[NSDictionary class]]) {
QNUploadData *data = [QNUploadData dataFromDictionary:dataInfo];
if (data == nil) {
return nil;
}
[dataList addObject:data];
}
}
}
QNUploadInfoV2 *info = [QNUploadInfoV2 info:source];
[info setInfoFromDictionary:dictionary];
info.expireAt = expireAt;
info.uploadId = uploadId;
info.dataSize = dataSize;
info.dataList = dataList;
if (![type isEqualToString:kTypeValue] || ![[source getId] isEqualToString:[info getSourceId]]) {
return nil;
} else {
return info;
}
}
- (BOOL)isValid {
if (![super isValid]) {
return false;
}
if (!self.expireAt || !self.uploadId || self.uploadId.length == 0) {
return false;
}
return (self.expireAt.doubleValue - 2*3600) > [[NSDate date] timeIntervalSince1970];
}
- (BOOL)reloadSource {
self.isEOF = false;
self.readError = nil;
return [super reloadSource];
}
- (BOOL)isSameUploadInfo:(QNUploadInfo *)info {
if (![super isSameUploadInfo:info]) {
return false;
}
if (![info isKindOfClass:[QNUploadInfoV2 class]]) {
return false;
}
return self.dataSize == [(QNUploadInfoV2 *)info dataSize];
}
- (void)clearUploadState {
self.expireAt = nil;
self.uploadId = nil;
if (self.dataList == nil || self.dataList.count == 0) {
return;
}
[self.dataList enumerateObjectsUsingBlock:^(QNUploadData *data, NSUInteger idx, BOOL * _Nonnull stop) {
[data clearUploadState];
}];
}
- (void)checkInfoStateAndUpdate {
[self.dataList enumerateObjectsUsingBlock:^(QNUploadData *data, NSUInteger idx, BOOL * _Nonnull stop) {
[data checkStateAndUpdate];
}];
}
- (long long)uploadSize {
if (self.dataList == nil || self.dataList.count == 0) {
return 0;
}
__block long long uploadSize = 0;
[self.dataList enumerateObjectsUsingBlock:^(QNUploadData *data, NSUInteger idx, BOOL * _Nonnull stop) {
uploadSize += [data uploadSize];
}];
return uploadSize;
}
- (BOOL)isAllUploaded {
if (!_isEOF) {
return false;
}
if (self.dataList == nil || self.dataList.count == 0) {
return true;
}
__block BOOL isAllUploaded = true;
[self.dataList enumerateObjectsUsingBlock:^(QNUploadData *data, NSUInteger idx, BOOL * _Nonnull stop) {
if (!data.isUploaded) {
isAllUploaded = false;
*stop = true;
}
}];
return isAllUploaded;
}
- (NSDictionary *)toDictionary {
NSMutableDictionary *dictionary = [[super toDictionary] mutableCopy];
if (dictionary == nil) {
dictionary = [NSMutableDictionary dictionary];
}
[dictionary setObject:kTypeValue forKey:kQNUploadInfoTypeKey];
[dictionary setObject:@(self.dataSize) forKey:@"dataSize"];
[dictionary setObject:self.expireAt ?: 0 forKey:@"expireAt"];
[dictionary setObject:self.uploadId ?: @"" forKey:@"uploadId"];
if (self.dataList != nil && self.dataList.count != 0) {
NSMutableArray *blockInfoList = [NSMutableArray array];
[self.dataList enumerateObjectsUsingBlock:^(QNUploadData *data, NSUInteger idx, BOOL * _Nonnull stop) {
[blockInfoList addObject:[data toDictionary]];
}];
[dictionary setObject:[blockInfoList copy] forKey:@"dataList"];
}
return [dictionary copy];
}
- (NSInteger)getPartIndexOfData:(QNUploadData *)data {
return data.index + 1;
}
- (QNUploadData *)nextUploadData:(NSError **)error {
// dataList data
QNUploadData *data = [self nextUploadDataFormDataList];
// dataList data
if (data == nil) {
if (self.isEOF) {
return nil;
} else if (self.readError) {
*error = self.readError;
return nil;
}
// block
long long dataOffset = 0;
if (self.dataList.count > 0) {
QNUploadData *lastData = self.dataList[self.dataList.count - 1];
dataOffset = lastData.offset + lastData.size;
}
data = [[QNUploadData alloc] initWithOffset:dataOffset dataSize:self.dataSize index:self.dataList.count];
}
QNUploadData*loadData = [self loadData:data error:error];
if (*error != nil) {
self.readError = *error;
return nil;
}
if (loadData == nil) {
// 没有加在到 data, 也即数据源读取结束
self.isEOF = true;
// 有多余的 data 则移除,移除中包含 data
if (self.dataList.count > data.index) {
self.dataList = [[self.dataList subarrayWithRange:NSMakeRange(0, data.index)] mutableCopy];
}
} else {
// 加在到 data
if (loadData.index == self.dataList.count) {
// 新块data index 等于 dataList size 则为新创建 block需要加入 dataList
[self.dataList addObject:loadData];
} else if (loadData != data) {
// 更换块:重新加在了 data 更换信息
[self.dataList replaceObjectAtIndex:loadData.index withObject:loadData];
}
// 数据源读取结束,块读取大小小于预期,读取结束
if (loadData.size < data.size) {
self.isEOF = true;
// 有多余的 data 则移除,移除中不包含 data
if (self.dataList.count > data.index + 1) {
self.dataList = [[self.dataList subarrayWithRange:NSMakeRange(0, data.index + 1)] mutableCopy];
}
}
}
return loadData;
}
- (QNUploadData *)nextUploadDataFormDataList {
if (self.dataList == nil || self.dataList.count == 0) {
return nil;
}
__block QNUploadData *data = nil;
[self.dataList enumerateObjectsUsingBlock:^(QNUploadData *dataP, NSUInteger idx, BOOL * _Nonnull stop) {
if ([dataP needToUpload]) {
data = dataP;
*stop = true;
}
}];
return data;
}
//
// 1.
// 2.
// 2.1 EOF null
// 2.2
// 2.2.1
// 2.2.2
- (QNUploadData *)loadData:(QNUploadData *)data error:(NSError **)error {
if (data == nil) {
return nil;
}
//
if (data.data != nil) {
return data;
}
// block
// data dataBytes
NSData *dataBytes = [self readData:(NSInteger)data.size dataOffset:data.offset error:error];
if (*error != nil) {
return nil;
}
// 没有数据不需要上传
if (dataBytes == nil || dataBytes.length == 0) {
return nil;
}
NSString *md5 = [dataBytes qn_md5];
// 判断当前 block 的数据是否和实际数据吻合,不吻合则之前 block 被抛弃,重新创建 block
if (dataBytes.length != data.size || data.md5 == nil || ![data.md5 isEqualToString:md5]) {
data = [[QNUploadData alloc] initWithOffset:data.offset dataSize:dataBytes.length index:data.index];
data.md5 = md5;
}
if (data.etag == nil || data.etag.length == 0) {
data.data = dataBytes;
data.state = QNUploadStateWaitToUpload;
} else {
data.state = QNUploadStateComplete;
}
return data;
}
- (NSArray <NSDictionary <NSString *, NSObject *> *> *)getPartInfoArray {
if (self.uploadId == nil || self.uploadId.length == 0) {
return nil;
}
NSMutableArray *infoArray = [NSMutableArray array];
[self.dataList enumerateObjectsUsingBlock:^(QNUploadData *data, NSUInteger idx, BOOL * _Nonnull stop) {
if (data.state == QNUploadStateComplete && data.etag != nil) {
[infoArray addObject:@{@"etag" : data.etag,
@"partNumber" : @([self getPartIndexOfData:data])}];
}
}];
return [infoArray copy];
}
@end