Ver código fonte

1.两个上传任务同时进入初步调试

huangxiaodong 10 meses atrás
pai
commit
fc145c786b

+ 24 - 0
创维盒子/双子星云手机.xcodeproj/project.pbxproj

@@ -808,6 +808,14 @@
 		6BB573222C7D7D8900713351 /* PCLoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BB573202C7D7D8900713351 /* PCLoginViewController.m */; };
 		6BB573232C7D7D8900713351 /* PCLoginViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BB5731F2C7D7D8900713351 /* PCLoginViewController.h */; };
 		6BB573242C7D7D8900713351 /* PCLoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BB573202C7D7D8900713351 /* PCLoginViewController.m */; };
+		6BB573272C7DC36600713351 /* nasMixUploadManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BB573252C7DC36600713351 /* nasMixUploadManager.h */; };
+		6BB573282C7DC36600713351 /* nasMixUploadManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BB573262C7DC36600713351 /* nasMixUploadManager.m */; };
+		6BB573292C7DC36600713351 /* nasMixUploadManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BB573252C7DC36600713351 /* nasMixUploadManager.h */; };
+		6BB5732A2C7DC36600713351 /* nasMixUploadManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BB573262C7DC36600713351 /* nasMixUploadManager.m */; };
+		6BB5732D2C7DC7A300713351 /* customUploadOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BB5732B2C7DC7A300713351 /* customUploadOperation.h */; };
+		6BB5732E2C7DC7A300713351 /* customUploadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BB5732C2C7DC7A300713351 /* customUploadOperation.m */; };
+		6BB5732F2C7DC7A300713351 /* customUploadOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BB5732B2C7DC7A300713351 /* customUploadOperation.h */; };
+		6BB573302C7DC7A300713351 /* customUploadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BB5732C2C7DC7A300713351 /* customUploadOperation.m */; };
 		6BB852282C4F7FE600570BF6 /* playingAudioGif.gif in Resources */ = {isa = PBXBuildFile; fileRef = 6BB852272C4F7FE500570BF6 /* playingAudioGif.gif */; };
 		6BB852292C4F7FE600570BF6 /* playingAudioGif.gif in Resources */ = {isa = PBXBuildFile; fileRef = 6BB852272C4F7FE500570BF6 /* playingAudioGif.gif */; };
 		6BBB35D92AE7645200E4A59B /* RunInBackground.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 6BBB35D62AE7645200E4A59B /* RunInBackground.mp3 */; };
@@ -1961,6 +1969,10 @@
 		6BB5731A2C7D6E1D00713351 /* scanToPCLoginViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = scanToPCLoginViewController.m; sourceTree = "<group>"; };
 		6BB5731F2C7D7D8900713351 /* PCLoginViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PCLoginViewController.h; sourceTree = "<group>"; };
 		6BB573202C7D7D8900713351 /* PCLoginViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PCLoginViewController.m; sourceTree = "<group>"; };
+		6BB573252C7DC36600713351 /* nasMixUploadManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = nasMixUploadManager.h; sourceTree = "<group>"; };
+		6BB573262C7DC36600713351 /* nasMixUploadManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = nasMixUploadManager.m; sourceTree = "<group>"; };
+		6BB5732B2C7DC7A300713351 /* customUploadOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = customUploadOperation.h; sourceTree = "<group>"; };
+		6BB5732C2C7DC7A300713351 /* customUploadOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = customUploadOperation.m; sourceTree = "<group>"; };
 		6BB852272C4F7FE500570BF6 /* playingAudioGif.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = playingAudioGif.gif; sourceTree = "<group>"; };
 		6BBB35D62AE7645200E4A59B /* RunInBackground.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = RunInBackground.mp3; sourceTree = "<group>"; };
 		6BBB35DB2AE76AD800E4A59B /* AudioSessionObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioSessionObject.h; sourceTree = "<group>"; };
@@ -3298,6 +3310,10 @@
 			children = (
 				6B9773992C637C4800213317 /* nasUploadManager.h */,
 				6B97739A2C637C4800213317 /* nasUploadManager.m */,
+				6BB5732B2C7DC7A300713351 /* customUploadOperation.h */,
+				6BB5732C2C7DC7A300713351 /* customUploadOperation.m */,
+				6BB573252C7DC36600713351 /* nasMixUploadManager.h */,
+				6BB573262C7DC36600713351 /* nasMixUploadManager.m */,
 				6B97739F2C637E3A00213317 /* nasUploadFileManager.h */,
 				6B9773A02C637E3A00213317 /* nasUploadFileManager.m */,
 				6BEF9B832C64CDD300142B75 /* frpUploadModel.h */,
@@ -3943,6 +3959,7 @@
 				6B42A2112C40DC3D000555BB /* previewLandscapeTopMoreView.h in Headers */,
 				6B7272572B0DAF7600C03F87 /* couldPhoneBaseInfoModel.h in Headers */,
 				186820212AB98600005702A6 /* QRCodeScanViewController.h in Headers */,
+				6BB573272C7DC36600713351 /* nasMixUploadManager.h in Headers */,
 				6B5D40332B4BE358000965CF /* downloadFileBottomView.h in Headers */,
 				6B1FBD222B43DAD200926382 /* backupsSetViewController.h in Headers */,
 				6B8FF6B92B04E19600800981 /* uploadFileRecordheadView.h in Headers */,
@@ -4045,6 +4062,7 @@
 				6B34DC6D2BF2070D002DD1EF /* titleLabelReusableView.h in Headers */,
 				6B304E982BEF6058004F5580 /* customShareManageTool.h in Headers */,
 				6B5D402F2B4BCBC1000965CF /* downLoadPreViewCell.h in Headers */,
+				6BB5732D2C7DC7A300713351 /* customUploadOperation.h in Headers */,
 				6B0581AD2AFCF57300D37290 /* AJPhotoGroupView.h in Headers */,
 				6B3AD6842BF48DBA0096D6B7 /* shareRecordDetailsHWViewController.h in Headers */,
 				6B1F7FDC2C00ABAB00954720 /* downStatusModel.h in Headers */,
@@ -4216,6 +4234,7 @@
 				6B42A2132C40DC3D000555BB /* previewLandscapeTopMoreView.h in Headers */,
 				6BD506D92B9576A4006E7CB0 /* couldPhoneBaseInfoModel.h in Headers */,
 				6BD506DA2B9576A4006E7CB0 /* QRCodeScanViewController.h in Headers */,
+				6BB573292C7DC36600713351 /* nasMixUploadManager.h in Headers */,
 				6BD506DB2B9576A4006E7CB0 /* downloadFileBottomView.h in Headers */,
 				6BD506DC2B9576A4006E7CB0 /* backupsSetViewController.h in Headers */,
 				6BD506DD2B9576A4006E7CB0 /* uploadFileRecordheadView.h in Headers */,
@@ -4318,6 +4337,7 @@
 				6B34DC6F2BF2070D002DD1EF /* titleLabelReusableView.h in Headers */,
 				6B304E992BEF6058004F5580 /* customShareManageTool.h in Headers */,
 				6BD507032B9576A4006E7CB0 /* downLoadPreViewCell.h in Headers */,
+				6BB5732F2C7DC7A300713351 /* customUploadOperation.h in Headers */,
 				6BD507042B9576A4006E7CB0 /* AJPhotoGroupView.h in Headers */,
 				6B3AD6872BF48DBA0096D6B7 /* shareRecordDetailsHWViewController.h in Headers */,
 				6B1F7FDE2C00ABAB00954720 /* downStatusModel.h in Headers */,
@@ -4909,11 +4929,13 @@
 				6BD5076F2B9576A4006E7CB0 /* uploadFileRecordTableViewHeadView.m in Sources */,
 				6BD507702B9576A4006E7CB0 /* JSONHTTPClient.m in Sources */,
 				6B4C0F752C0314BA0070EF2E /* DFPlayerTool.m in Sources */,
+				6BB573302C7DC7A300713351 /* customUploadOperation.m in Sources */,
 				6BD507712B9576A4006E7CB0 /* AFImageDownloader.m in Sources */,
 				6BD507722B9576A4006E7CB0 /* UIColor+HZXColor.m in Sources */,
 				6B238C912C60AAE200C5AC2F /* nasDownloadManager.m in Sources */,
 				6BD507732B9576A4006E7CB0 /* CalculatorViewController.m in Sources */,
 				6B5BE5942BFCA5FA00A1B9B3 /* videoPlayViewController.m in Sources */,
+				6BB5732A2C7DC36600713351 /* nasMixUploadManager.m in Sources */,
 				6B4C0F6D2C0314BA0070EF2E /* DFPlayerRequestManager.m in Sources */,
 				6BD507742B9576A4006E7CB0 /* extraMediaEventModel.m in Sources */,
 				6B5D86762C22C63F008D25EA /* NASCommonUsedView.m in Sources */,
@@ -5264,11 +5286,13 @@
 				6B72724C2B0AF59200C03F87 /* uploadFileRecordTableViewHeadView.m in Sources */,
 				183AE6082A89CE3C00B11CB0 /* JSONHTTPClient.m in Sources */,
 				6B4C0F742C0314BA0070EF2E /* DFPlayerTool.m in Sources */,
+				6BB5732E2C7DC7A300713351 /* customUploadOperation.m in Sources */,
 				183AE6532A8A2CF000B11CB0 /* AFImageDownloader.m in Sources */,
 				A003F6B327D841EE00715CBF /* UIColor+HZXColor.m in Sources */,
 				6B238C8E2C60AAE200C5AC2F /* nasDownloadManager.m in Sources */,
 				18E557222A3C5D75005CC84B /* CalculatorViewController.m in Sources */,
 				6B5BE5922BFCA5FA00A1B9B3 /* videoPlayViewController.m in Sources */,
+				6BB573282C7DC36600713351 /* nasMixUploadManager.m in Sources */,
 				6B4C0F6C2C0314BA0070EF2E /* DFPlayerRequestManager.m in Sources */,
 				6B1CC2C72B677F3E00AD4217 /* extraMediaEventModel.m in Sources */,
 				6B5D86732C22C63F008D25EA /* NASCommonUsedView.m in Sources */,

+ 1 - 1
创维盒子/双子星云手机/AppDelegate/PrefixHeader.pch

@@ -122,7 +122,7 @@ isBangsScreen; \
 #define EachPieceSzie (2*1024*1024) //每片上传文件大小切割
 #define cutVideoPieceSzie (3 * EachPieceSzie) //视频每次切片多少(切完上传再切一次)
 
-#define MaxNasUploadPieceSzie (50*1024*1024) //frp上传 限制每片最大xx M
+#define MaxNasUploadPieceSzie (30*1024*1024) //frp上传 限制每片最大xx M
 #define keyToForgetPwd @"%==%"
 
 #define FileService            @"http://file.phone.androidscloud.com:8210/document/file/lowLevelMultipartUpload"

+ 32 - 0
创维盒子/双子星云手机/NAS/nasUploadManager/customUploadOperation.h

@@ -0,0 +1,32 @@
+//
+//  customUploadOperation.h
+//  双子星云手机
+//
+//  Created by xd h on 2024/8/27.
+//
+
+#import <Foundation/Foundation.h>
+#import "uploadFileDataModel.h"
+
+/**
+ *   检测文件是否存在拿到结果 -1 失败  0 是正常(文件不存在 或者存在了 但是未上传完成) 1 文件已经存在并且上传完成了
+ */
+typedef void (^uploadStateFileExistRet) (NSInteger state);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface customUploadOperation : NSObject
+
+@property(nonatomic,strong) uploadFileDataModel *fileModel;
+
+/** 上传任务 */
+@property (nonatomic,strong,nullable)NSURLSession *session;
+
+/** 上传任务 */
+@property (nonatomic,strong,nullable)NSURLSessionDataTask *dataTask;
+
+@property(nonatomic,assign) long  onceDataLengt;//当前的片的长度
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 16 - 0
创维盒子/双子星云手机/NAS/nasUploadManager/customUploadOperation.m

@@ -0,0 +1,16 @@
+//
+//  customUploadOperation.m
+//  双子星云手机
+//
+//  Created by xd h on 2024/8/27.
+//
+
+#import "customUploadOperation.h"
+
+//#define Kboundary2 @"Boundaryhxd"
+//#define KNewLine2 [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]
+
+@implementation customUploadOperation
+
+
+@end

+ 31 - 0
创维盒子/双子星云手机/NAS/nasUploadManager/nasMixUploadManager.h

@@ -0,0 +1,31 @@
+//
+//  nasMixUploadManager.h
+//  双子星云手机
+//
+//  Created by xd h on 2024/8/27.
+//
+
+#import <Foundation/Foundation.h>
+#import "uploadFileDataModel.h"
+
+/** 上传失败通知 */
+#define  nasUploadTaskExeError      @"nasUploadTaskExeError"
+/** 上传完成通知 */
+#define  nasUploadTaskExeEnd        @"nasUploadTaskExeEnd"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface nasMixUploadManager : NSObject
+
+@property(nonatomic,assign) NSInteger maxUploadLoadCount;//默认一个
+/** 实例化对象(单例) */
++ (instancetype)shareManager;
+
+#pragma mark - 队列中的任务进行操作
+
+/** 添加要上传的 模型  */
+- (void)addDownloadWithModels:(NSArray *)fileModels;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 728 - 0
创维盒子/双子星云手机/NAS/nasUploadManager/nasMixUploadManager.m

@@ -0,0 +1,728 @@
+//
+//  nasMixUploadManager.m
+//  双子星云手机
+//
+//  Created by xd h on 2024/8/27.
+//
+
+#import "nasMixUploadManager.h"
+#import "customUploadOperation.h"
+#import "nasUploadFileManager.h"
+#import "frpFileExistModel.h"
+#import "frpUploadModel.h"
+
+#define Kboundary2 @"Boundaryhxd"
+
+@interface nasMixUploadManager ()<NSURLSessionDataDelegate>
+//排队等候下载的上传地址数组
+@property(nonatomic,strong) NSMutableArray *uploadWaitingUrlArr;
+//正在下载的上传地址数组
+@property(nonatomic,strong) NSMutableArray *uploadingOperationArr;
+@end
+
+@implementation nasMixUploadManager
++ (instancetype)shareManager {
+    static nasMixUploadManager *_instance;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        _instance = [[self alloc] init];
+    });
+    return _instance;
+}
+
+- (instancetype)init {
+
+    if (self = [super init]) {
+        _maxUploadLoadCount = 2;
+        //[self registeNotification];
+    }
+    return self;
+}
+
+/** 添加要上传的 模型  */
+- (void)addDownloadWithModels:(NSArray *)fileModels{
+    
+    for (uploadFileDataModel *model in fileModels) {
+        BOOL needAddType = YES;
+        
+        //1. 排查上传中
+        for (customUploadOperation *operationDoing in self.uploadingOperationArr) {
+            if([operationDoing.fileModel.filename isEqualToString:model.filename]){
+                needAddType = NO;
+                break;
+            }
+        }
+        
+        //1. 排查等待下载
+        for (uploadFileDataModel *waitModel in self.uploadWaitingUrlArr) {
+            if([waitModel.filename isEqualToString:model.filename]){
+                needAddType = NO;
+                break;
+            }
+        }
+        
+        if(needAddType){
+            [self.uploadWaitingUrlArr addObject:model];
+        }
+    }
+    
+    //启动上传
+    [self beginUpload];
+}
+
+//在添加XX后 启动下载
+- (void)beginUpload
+{
+    @synchronized (self) {
+        if(self.uploadingOperationArr.count == _maxUploadLoadCount){
+            HLog(@"正在上传的数量达到了最大值 %ld",_maxUploadLoadCount)
+            return;
+        }
+        
+        if(self.uploadWaitingUrlArr.count == 0){
+            HLog(@"没有等待中的上传任务")
+            return;
+        }
+        
+        NSInteger canAddTaskNumber = _maxUploadLoadCount - self.uploadingOperationArr.count;
+        
+        for (int i=0; i<canAddTaskNumber; i++) {
+            
+            if(self.uploadWaitingUrlArr.count >= 1){
+                //创建上传任务
+                uploadFileDataModel *WaitingModel = self.uploadWaitingUrlArr.firstObject;
+                
+                __block customUploadOperation * operation =  [customUploadOperation new];
+                operation.fileModel = WaitingModel;
+                
+                //等待下载中的任务
+                [self.uploadWaitingUrlArr removeObjectAtIndex:0];
+                //添加到下载中数组
+                [self.uploadingOperationArr addObject:operation];
+                
+                [self checkFileUploadStateWithOperation:operation];
+                
+                //[weakSelf handleTaskDidUploadWith:operation withState:state];
+            }
+            
+        }
+    
+    }
+    
+}
+
+#pragma mark 检测文件是否上传过了
+- (void)checkFileUploadStateWithOperation:(customUploadOperation*)operation
+{
+    NSMutableDictionary*paraDict = [NSMutableDictionary new];
+    
+    if(operation.fileModel.savePath){
+        NSString *absPath = [[NSString alloc] initWithFormat:@"%@%@",operation.fileModel.savePath,operation.fileModel.filename];
+        [paraDict setValue:absPath forKey:@"absPath"];
+        
+        NSNumber *totalBytesNumber = [NSNumber numberWithLong:operation.fileModel.totalBytes];
+        [paraDict setValue:totalBytesNumber forKey:@"fileSize"];
+    }
+    
+    KWeakSelf
+    [[netWorkManager shareInstance] cloudPhoneGETCallBackCode:@"isFileExist" Parameters:paraDict success:^(id  _Nonnull responseObject) {
+        
+        frpFileExistModel *model = [[frpFileExistModel alloc] initWithDictionary:responseObject error:nil];
+        if(model && model.status == 0){
+            [weakSelf checkFileUploadStateFunAfterNetWith:model WithOperation:operation];
+        }
+        else{
+            //FileExistRet(-1);
+        }
+    } failure:^(NSError * _Nonnull error) {
+        HLog(@"%@",error)
+        //FileExistRet(-1);
+    }];
+    
+}
+
+#pragma mark 检测分家是否存在后处理 是否要上传
+- (void)checkFileUploadStateFunAfterNetWith:(frpFileExistModel*)model WithOperation:(customUploadOperation*)operation
+{
+    if(!model){
+        return;
+    }
+    
+    operation.fileModel.didUploadBytes = 0;
+    operation.fileModel.taskId = model.data.taskId;
+    
+    if(!model.data.exist){//未上传过
+        [self prepareToUploadFileWithOperation:operation];
+        //FileExistRet(0);
+    }
+    else if(model.data.isComplete){//上传过了 并且文件上传完了
+        //判断下文件创建长度是否一致 一致则是上传完了 不一致 重新上传一个 可能是同名的文件而已
+//        if(model.data.size >= _curUploadFileDataModel.totalBytes){//上传完了
+//            HLog(@"222");
+//        }
+//        else{
+//
+//        }
+        
+        //FileExistRet(1);
+        
+    }
+    else{//上传过了 未上传完成
+        operation.fileModel.didUploadBytes = model.data.size;
+        [self prepareToUploadFileWithOperation:operation];
+        //FileExistRet(0);
+    }
+}
+
+
+#pragma mark 处理任务失败
+
+
+#pragma mark 准备上传文件
+- (void)prepareToUploadFileWithOperation:(customUploadOperation*)operation
+{
+    NSMutableDictionary *paraDict = [NSMutableDictionary new];
+    
+    NSString* taskUid  = operation.fileModel.taskId;
+    if(!taskUid || taskUid.length == 0){
+        taskUid = [iTools getTaskUidStr];
+        operation.fileModel.taskId = taskUid;
+    }
+    
+    [paraDict setObject:taskUid forKey:@"taskId"];
+    [paraDict setObject:@0 forKey:@"position"];
+    [paraDict setObject:@"true" forKey:@"isLast"];
+    if(operation.fileModel.savePath){
+        [paraDict setObject:operation.fileModel.savePath forKey:@"savePath"];
+    }
+    else{
+        HLog(@"获取保存路径失败")
+        return;
+    }
+    
+    if(operation.fileModel.filename){
+        [paraDict setObject:operation.fileModel.filename forKey:@"filename"];
+    }
+    else{
+        HLog(@"获取用户名失败")
+        return;
+    }
+    
+    KWeakSelf
+    if(operation.fileModel.curUploadFileType == uploadFileTypeImage){
+        [paraDict setObject:@1 forKey:@"imageType"];
+        
+        if(!operation.fileModel.imageData){
+            
+            NSString*pathStr = [cachesFileManager getFilePathWithName:operation.fileModel.filename type:operation.fileModel.curUploadFileType];
+            NSData *imageData = [NSData dataWithContentsOfFile:pathStr];
+            
+            if (!imageData) {
+                
+                if(!operation.fileModel.asset){
+                    NSString *curLocalIdentifier = operation.fileModel.localIdentifier;
+                    PHFetchResult *fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[curLocalIdentifier] options:nil];
+                    PHAsset *asset = fetchResult.firstObject;
+                    operation.fileModel.asset = asset;
+                }
+                
+                [[PHImageManager defaultManager] requestImageDataForAsset:operation.fileModel.asset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
+                        // 直接得到最终的 NSData 数据
+                        if (imageData) {
+                            operation.fileModel.imageData = imageData;
+                            [weakSelf  afterGetImageDataFunWithOperation:operation];
+                        }
+                        else{
+                            [weakSelf handleUploadFailOneFileBy:operation];
+                        }
+                }];
+                return;
+            }
+            
+            operation.fileModel.imageData = imageData;
+        }
+        
+        
+        NSData *curData = operation.fileModel.imageData;
+        operation.onceDataLengt = [curData length];
+        
+        [self startUpload:paraDict operation:operation data:curData success:^(id  _Nonnull responseObject) {
+            frpUploadModel *model = [[frpUploadModel alloc] initWithDictionary:responseObject error:nil];
+            if(model && model.position == operation.fileModel.totalBytes){
+                HLog(@"%@上传完成 000",operation.fileModel.filename)
+                [weakSelf handleUploadDoneOneFileBy:operation];
+            }
+            else{
+                HLog(@"%@上传完成一片 %ld",operation.fileModel.filename,model.position)
+            }
+        } faild:^(NSError * _Nonnull error) {
+            HLog(@"%@上传失败",operation.fileModel.filename)
+            [weakSelf handleUploadFailOneFileBy:operation];
+        }];
+    }
+    else{
+        [paraDict setObject:@1 forKey:@"videoType"];
+        [paraDict setObject:@"false" forKey:@"isLast"];
+
+        if(![cachesFileManager checkFileIsSaveState:operation.fileModel.filename withType:uploadFileTypeVideo]){
+            
+            if(!operation.fileModel.asset){
+                NSString *curLocalIdentifier = operation.fileModel.localIdentifier;
+                PHFetchResult *fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[curLocalIdentifier] options:nil];
+                PHAsset *asset = fetchResult.firstObject;
+                operation.fileModel.asset = asset;
+            }
+            
+
+            //真正的视频数据
+            PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
+            options.version = PHVideoRequestOptionsVersionOriginal;
+            [[PHImageManager defaultManager] requestAVAssetForVideo:operation.fileModel.asset options:options resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
+                if ([asset isKindOfClass:[AVURLAsset class]]) {
+                    
+                    AVURLAsset* urlAsset = (AVURLAsset*)asset;
+                    
+                    BOOL isSuc = [cachesFileManager copyVideoItemAtPath:[urlAsset.URL path] fileName:operation.fileModel.filename error:nil];
+                    
+                    if (isSuc) {
+                        [weakSelf  afterGetVideoDataFunWithOperation:operation];
+                    }
+                    else{
+                        [weakSelf handleUploadFailOneFileBy:operation];
+                    }
+                }
+                else{
+                    [weakSelf handleUploadFailOneFileBy:operation];
+                }
+            }];
+            
+            return;
+        }
+        
+        long curPosition = operation.fileModel.didUploadBytes;
+        [self beginUploadVideoDataFunBy:operation with:curPosition withPara:paraDict success:^(id  _Nonnull responseObject) {
+            
+        } faild:^(NSError * _Nonnull error) {
+            
+        }];
+    }
+    
+}
+
+#pragma mark 视频上传
+- (void)beginUploadVideoDataFunBy:(customUploadOperation*)operation with:(NSInteger)position withPara:(NSMutableDictionary*)paraDict success:(netWork_Success)success faild:(netWork_Faild)faildStr
+{
+
+    BOOL isLastPicece = NO;
+    if((operation.fileModel.totalBytes - position) <= MaxNasUploadPieceSzie){
+        [paraDict setObject:@"true" forKey:@"isLast"];
+        isLastPicece = YES;
+    }
+    else{
+        [paraDict setObject:@"false" forKey:@"isLast"];
+    }
+    
+    [paraDict setObject:[NSNumber numberWithLong:position] forKey:@"position"];
+    
+    //视频数据切片
+    __block NSData *videoData = [self cutVideoFileFunAtIndex:position withMaxLenght:MaxNasUploadPieceSzie withModel:operation.fileModel];
+    
+    if(!videoData ||videoData.length ==0){
+        HLog(@"视频没获取到")
+        [self handleUploadFailOneFileBy:operation];
+        return;
+    }
+        
+    operation.onceDataLengt = [videoData length];
+    KWeakSelf
+    [self startUpload:paraDict operation:operation data:videoData success:^(id  _Nonnull responseObject) {
+        frpUploadModel *model = [[frpUploadModel alloc] initWithDictionary:responseObject error:nil];
+        if(model && model.position >= operation.fileModel.totalBytes){
+            HLog(@"%@上传完成 000",operation.fileModel.filename)
+            [weakSelf handleUploadDoneOneFileBy:operation];
+        }
+        else{
+            HLog(@"%@上传完成一片 %ld",operation.fileModel.filename,model.position)
+            
+            [weakSelf beginUploadVideoDataFunBy:operation with:model.position withPara:paraDict success:^(id  _Nonnull responseObject) {
+                success(responseObject);
+            } faild:^(NSError * _Nonnull error) {
+                NSError *err = error;
+                if(error.code != -999){
+                    faildStr(err);
+                }
+               
+            }];
+        }
+    } faild:^(NSError * _Nonnull error) {
+        HLog(@"%@上传失败",operation.fileModel.filename)
+        [weakSelf handleUploadFailOneFileBy:operation];
+    }];
+    
+}
+
+#pragma mark 分段读视频文件
+-(NSData*)cutVideoFileFunAtIndex:(NSUInteger)dataIndex withMaxLenght:(NSInteger)maxLengt withModel:(uploadFileDataModel*)dataModel{
+    NSString *filePath = [cachesFileManager getFilePathWithName:dataModel.filename type:uploadFileTypeVideo]; // 文件路径
+    
+    NSFileManager *manager0 = [NSFileManager defaultManager];
+    if(![manager0 fileExistsAtPath:filePath]) {
+     
+        return [NSData new];
+    }
+    
+    NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:filePath]; // 创建文件句柄
+      
+    // 设置分段读取的大小,这里以每次读取1KB为例
+    const NSUInteger chunkSize = maxLengt;//cutVideoPieceSzie;//5 * 1024 *1024;
+    NSMutableData *data = [NSMutableData data];
+    
+    if (fileHandle) {
+       
+        long long endOfFile = [fileHandle seekToEndOfFile];
+        
+        if(dataModel.totalBytes == 0
+           || dataModel.totalBytes < endOfFile){//异常处理
+            dataModel.totalBytes = endOfFile;
+        }
+        
+        //异常处理
+        if(endOfFile == dataIndex){
+            dataModel.totalBytes = endOfFile;
+            dataModel.didUploadBytes = endOfFile;
+            dataModel.curUploadStateType = uploadStateDone;
+            [fileHandle closeFile];
+            return  data;
+        }
+        
+        if (endOfFile >=  chunkSize) {
+            
+            // 读取文件的分段数据到某个位置
+            [fileHandle seekToFileOffset:dataIndex];
+            
+            // 读取文件的分段数据
+            NSData* chunk = [fileHandle readDataOfLength:chunkSize];
+            if (chunk) {
+                [data appendData:chunk];
+            }
+        }
+        else{
+            // 读取文件的分段数据到某个位置
+            [fileHandle seekToFileOffset:dataIndex];
+            
+            [data appendData:[fileHandle readDataToEndOfFile]];
+        }
+        
+        // 在这里可以对文件内容进行处理
+        // ...
+        
+        // 关闭文件句柄
+        [fileHandle closeFile];
+    }
+    
+    HLog(@"视频切片完成 dataIndex:%ld --长度:%ld",dataIndex,[data length])
+    return data;
+}
+
+#pragma mark 处理上传完成
+- (void)handleUploadDoneOneFileBy:(customUploadOperation*)operation
+{
+    [[NSNotificationCenter defaultCenter] postNotificationName:nasUploadTaskExeEnd object:operation.fileModel];
+    [_uploadingOperationArr removeObject:operation];
+    [self beginUpload];
+}
+
+#pragma mark 处理删除失败
+- (void)handleUploadFailOneFileBy:(customUploadOperation*)operation
+{
+    operation.fileModel.curUploadStateType = uploadStateFail;
+    [[NSNotificationCenter defaultCenter] postNotificationName:nasUploadTaskExeError object:operation.fileModel];
+    [_uploadingOperationArr removeObject:operation];
+    [self beginUpload];
+}
+
+#pragma mark 根据 asset 获取到图片数据
+- (void)afterGetImageDataFunWithOperation:(customUploadOperation*)operation
+{
+    [cachesFileManager getFileNameWithContent:operation.fileModel.imageData fileName:operation.fileModel.filename type:uploadFileTypeImage];
+    
+    [self prepareToUploadFileWithOperation:operation];
+}
+
+#pragma mark 根据 asset 获取到视频数据
+- (void)afterGetVideoDataFunWithOperation:(customUploadOperation*)operation
+{
+    
+    [self prepareToUploadFileWithOperation:operation];
+}
+
+#pragma mark 开始上传
+- (void)startUpload:(NSMutableDictionary *)params operation:(customUploadOperation*)operation data:(NSData *)data success:(netWork_Success)success faild:(netWork_Faild)faildStr {
+    
+    NSString *urlString = ksharedAppDelegate.NASFileByBoxService;
+    urlString = [[NSString alloc] initWithFormat:@"%@uploadFile",urlString];
+    NSURL *URL = [NSURL URLWithString:urlString];
+    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
+    [request setHTTPMethod:@"POST"];
+    
+    //请求体
+    NSMutableData *bodyData = [self getBodyDataWithRequest:request withModel:operation.fileModel withData:data withPara:params];
+    
+    //设置请求体
+    [request setHTTPMethod:@"POST"];
+    [request setHTTPBody:bodyData];
+    
+    //设置请求体长度
+    NSInteger length = [bodyData length];
+    [request setValue:[NSString stringWithFormat:@"%ld",length] forHTTPHeaderField:@"Content-Length"];
+    //设置 POST请求文件上传
+    [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary2]  forHTTPHeaderField:@"Content-Type"];
+
+    KWeakSelf
+    //回话对象
+    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
+    operation.session = session;
+    
+    //请求task
+    /*
+     第一个参数:请求对象
+     第二个参数:传递是要上传的数据(请求体)
+     第三个参数:
+     */
+    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:nil completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
+        //解析
+        [weakSelf handleCustomUploadResultBy:data withResponse:response withError:error success:success faild:faildStr];
+    }];
+    
+//    NSString *filePath = [cachesFileManager getFilePathWithName:dataModel.filename type:uploadFileTypeVideo]; // 文件路径
+//    NSURL *filePathUrl = [NSURL URLWithString:filePath];
+//
+//    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:filePathUrl completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
+//        HLog(@"data string:%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
+    //[weakSelf handleCustomUploadResultBy:data withResponse:response withError:error];
+//    }];
+    
+//    NSURLSessionDataTask *uploadTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
+//
+//        HLog(@"data string:%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
+    //[weakSelf handleCustomUploadResultBy:data withResponse:response withError:error];
+//
+////           NSJSONSerialization *object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
+////           NSDictionary *dict = (NSDictionary *)object;
+////           NSLog(@"=====%@",[dict objectForKey:@"success"]);
+//       }];
+
+    
+    //执行Task
+    [uploadTask resume];
+    operation.dataTask = uploadTask;
+}
+
+#pragma mark 用系统方法写的上传处理
+- (void)handleCustomUploadResultBy:(NSData*)data withResponse:(NSURLResponse*)response withError:(NSError*)error success:(netWork_Success)success faild:(netWork_Faild)faildStr{
+    if(error){
+        HLog(@"上传错误:%@",error)
+        faildStr(error);
+        return;
+    }
+    
+    NSJSONSerialization *object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
+    NSDictionary *dict = (NSDictionary *)object;
+    
+    frpUploadModel *model = [[frpUploadModel alloc] initWithDictionary:dict error:nil];
+    if(model && [model.msg isEqualToString:@"success"]){
+        success(dict);
+    }
+    else{
+        NSError *err = [NSError new];
+        faildStr(err);
+    }
+}
+
+- (NSMutableData *)getBodyDataWithRequest:(NSMutableURLRequest *)request withModel:(uploadFileDataModel*)dataModel withData:(NSData*)data  withPara:(NSMutableDictionary*)params{
+    
+    //1 边界符号要配置请求头里面去
+    /*
+     multipart/form-data 是表单格式
+     charset=utf-8 是utf-8编码
+     bounary 是表单开头
+     */
+    [request setValue:[NSString stringWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@", Kboundary2] forHTTPHeaderField:@"Content-Type"];
+    
+    /// body
+    NSMutableData *boydData = [NSMutableData data];
+    // 2.1 边界符号(开始边界)
+    
+    //2.1.1 其它参数
+    NSMutableString *paraString = [NSMutableString new];
+    //[paraString appendFormat:@"--%@\r\n",Kboundary];//\n:换行 \n:切换到行首
+    for (NSString *key in params) {
+        NSString *value = params[key];
+        [paraString appendFormat:@"--%@\r\n",Kboundary2];//\n:换行 \n:切换到行首
+        [paraString appendFormat:@"Content-Disposition: form-data; name=\"%@\"",key];
+        [paraString appendFormat:@"\r\n"];
+        [paraString appendFormat:@"\r\n"];
+        [paraString appendFormat:@"%@\r\n",value];
+    }
+    
+    //[boydData appendData:[paraString dataUsingEncoding:NSUTF8StringEncoding]];
+    
+    
+    // body每一个段内容以换行符作为结束标示
+    NSString *fileBeginBoundary = [NSString stringWithFormat:@"--%@\r\n", Kboundary2];
+    //[boydData appendData:[fileBeginBoundary dataUsingEncoding:NSUTF8StringEncoding]];
+    
+    [paraString appendString:fileBeginBoundary];
+    
+    // 2.2 属性配置 名字;key;类型
+    
+    NSString *serverFileKey = @"image";  //key
+    //NSString *serverFileKey = @"file";
+    NSString *serverContentTypes = @"image/png";  //类型
+    
+    if (dataModel.curUploadFileType == uploadFileTypeVideo) {
+        serverFileKey = @"video";
+        serverContentTypes = @"video/mp4";
+    }
+    
+    
+    NSString *serverFileName = dataModel.filename;  //name
+
+    
+    // filename已命名文件;  name相当于一个key, 这个名字和服务器保持一致
+    /*
+     理解key,表单发送给服务端,服务端拿到数据之后,可以将任务解析成一个字典了imageDict;图片数据会通过这个字典里面的name来获取图片(伪代码 image =  imageDict[serverFileKey])
+     */
+    //2.3 拼接数据(创建一个字符串来拼装)
+    NSMutableString *string = [NSMutableString new];
+    [string appendFormat:@"Content-Disposition:form-data; name=\"%@\"; filename=\"%@\" ", @"file", serverFileName];
+    //[string appendFormat:@"%@", KNewLine];
+    [string appendFormat:@"\r\n"];
+    [string appendFormat:@"Content-Type:%@", serverContentTypes];
+//    [string appendFormat:@"%@", KNewLine];
+//    [string appendFormat:@"%@", KNewLine];
+    [string appendFormat:@"\r\n"];
+    [string appendFormat:@"\r\n"];
+   // [boydData appendData:[string dataUsingEncoding:NSUTF8StringEncoding]];
+    
+    [paraString appendString:string];
+    [boydData appendData:[paraString dataUsingEncoding:NSUTF8StringEncoding]];
+    
+    // 2.3 拼接数据(拼接文件数据)
+    [boydData appendData:data];
+    
+    // 2.4 边界符号 (结束边界)
+    NSString *fileEndBoundary = [NSString stringWithFormat:@"\r\n--%@--", Kboundary2];
+    [boydData appendData:[fileEndBoundary dataUsingEncoding:NSUTF8StringEncoding]];
+    
+    return boydData;
+}
+
+#pragma mark 上传的文件已存在
+- (void)handleTaskDidUploadWith:(customUploadOperation*)operation withState:(NSInteger)state
+{
+    if(state == 1){
+        [[iToast makeText:NSLocalizedString(@"File_upload_file_already_exists",nil)] show];
+    }
+    
+    
+    [self.uploadingOperationArr removeObject:operation];
+    
+    NSMutableArray *delArr = [NSMutableArray new];
+    [delArr addObject:operation.fileModel];
+    
+    [[nasUploadFileManager shareInstance] deleteUploadFileRecordBy:delArr withDelCache:NO complete:^(BOOL isSuccess) {
+        if (isSuccess) {
+            
+        }
+    }];
+    
+    [self beginUpload];
+}
+    
+
+#pragma mark - <NSURLSessionDataDelegate>
+
+// ssl 服务 证书信任
+- (void)URLSession:(NSURLSession *)session
+didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
+ completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{
+    if(![challenge.protectionSpace.authenticationMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"]) {
+        return;
+    }
+    
+    // 信任该插件
+    NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust];
+    // 第一个参数 告诉系统如何处置
+    completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
+}
+
+//当请求协议是https的时候回调用该方法
+//Challenge 挑战 质询(受保护空间)
+//NSURLAuthenticationMethodServerTrust 服务器信任证书
+- (void)URLSession:(NSURLSession *)session
+              task:(NSURLSessionTask *)task
+didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
+ completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler {
+    
+    if(![challenge.protectionSpace.authenticationMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"]) {
+        return;
+    }
+    
+    // 信任该插件
+    NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust];
+    // 第一个参数 告诉系统如何处置
+    completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
+    
+}
+
+
+// 接受到响应调用
+- (void)URLSession:(NSURLSession *)session
+          dataTask:(NSURLSessionDataTask *)dataTask
+didReceiveResponse:(NSURLResponse *)response
+ completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
+    
+    completionHandler(NSURLSessionResponseAllow);
+}
+
+// 上传进度
+- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
+    
+    //每包发送的大小bytesSent,totalBytesSent已经上传了多少;totalBytesExpectedToSend总共要发送多少
+    // 32768 = 32KB
+    HLog(@"didSendBodyData: %lld--%lld-%lld", bytesSent, totalBytesSent, totalBytesExpectedToSend);
+    
+    for (customUploadOperation*operation in _uploadingOperationArr) {
+        if(operation.dataTask == task){
+            operation.fileModel.didUploadBytes += bytesSent;
+            
+            //调整下大小 因为上传的数据 除了data 长度 还包含了 参数大小
+            if(totalBytesSent == totalBytesExpectedToSend){
+                operation.fileModel.didUploadBytes -= (totalBytesExpectedToSend - operation.onceDataLengt);
+            }
+            
+            [[NSNotificationCenter defaultCenter] postNotificationName:uploadFileRefreshNotification object:operation.fileModel];
+            break;
+        }
+    }
+    
+}
+
+#pragma mark - lazy load
+- (NSMutableArray *)uploadWaitingUrlArr {
+    
+    if (!_uploadWaitingUrlArr) {
+        _uploadWaitingUrlArr = [NSMutableArray array];
+    }
+    return _uploadWaitingUrlArr;
+}
+
+- (NSMutableArray *)uploadingOperationArr {
+    
+    if (!_uploadingOperationArr) {
+        _uploadingOperationArr = [NSMutableArray array];
+    }
+    return _uploadingOperationArr;
+}
+@end

+ 2 - 0
创维盒子/双子星云手机/NAS/nasUploadManager/nasUploadFileManager.h

@@ -9,6 +9,8 @@
 #import "uploadFileManager.h"
 #import "frpUploadModel.h"
 #import "frpFileExistModel.h"
+#import "nasMixUploadManager.h"
+
 NS_ASSUME_NONNULL_BEGIN
 
 #define nasUpLoadFile_tableName [[NSString alloc] initWithFormat:@"upLoadFile_tableName_%@",[connectDeviceManager shareInstance].DeviceThirdIdMod.data.sn]

+ 35 - 1
创维盒子/双子星云手机/NAS/nasUploadManager/nasUploadFileManager.m

@@ -31,6 +31,9 @@
 {
     _maxUploadingNumber = 1;
     _uploadingModelArr = [NSMutableArray new];
+    
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(uploadTaskFinishedNoti:) name:nasUploadTaskExeEnd object:nil];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(uploadTaskErrorNoti:) name:nasUploadTaskExeError object:nil];
 }
 
 #pragma mark 读取数据库数据
@@ -242,9 +245,40 @@
     
     _fileModelDataArr = [NSMutableArray arrayWithArray:totalArr[0]];
     
-    [self beginUploadFileFun];
+    //多任务同时进行模式
+    [[nasMixUploadManager shareManager] addDownloadWithModels:_fileModelDataArr];
+    [_fileModelDataArr removeAllObjects];
+    
+   // [self beginUploadFileFun];
+}
+
+#pragma mark 上传完成
+- (void)uploadTaskFinishedNoti:(NSNotification *)notification
+{
+    uploadFileDataModel *model = notification.object;
+    
+    if(!model)return;
+    
+    model.curUploadStateType = uploadStateDone;
+    [self nasUploadFileChangeingOneFileFunBy:model];
+    [self uploadFileDoneOneFunWith:model];
+    [self deleteCacheDataBy:model];
 }
 
+#pragma mark 上传失败
+- (void)uploadTaskErrorNoti:(NSNotification *)notification
+{
+    uploadFileDataModel *model = notification.object;
+    
+    if(!model)return;
+    
+    model.curUploadStateType = uploadStateFail;
+    [self nasUploadFileChangeingOneFileFunBy:model];
+    [self uploadFileFailOneFunWith:model];
+    [self deleteCacheDataBy:model];
+}
+    
+
 - (void)beginUploadFileFun
 {
 //    if(_isUploadIngType && _reUploadIngSelectIndex <= 0){