| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- //
- // WSUploadloadSession.m
- // zhuxun
- //
- // Created by winsoft on 17/6/26.
- //
- //
- #import "WSUploadSession.h"
- #import "AsyncSocket.h"
- #import "DataInputStream.h"
- #import "DataOutputStream.h"
- #import "NSData+crc32.h"
- #import "NSData+MD5Digest.h"
- #import "NSDictionary+JSON.h"
- #import "NSString+Extension.h"
- #import "FileUtils.h"
- #define ChunkSize 8*1024
- @interface WSUploadSession()
- @property (nonatomic , copy) NSString *fileName;
- @property (nonatomic, copy)NSString *filePath;
- @property (nonatomic, copy)NSString *uuid;
- //@property (nonatomic, assign)AttachType attachMentType;
- /*文件发送相关*/
- @property (nonatomic, strong)AsyncSocket *asyncSocket;
- @property (nonatomic, strong)NSSet *runLoopModes;
- @property (nonatomic, copy)NSMutableData *sendData;
- @property (nonatomic, copy)NSString *md5;
- @property (nonatomic, assign)unsigned long long fileSize;
- //初始偏移量
- @property (nonatomic, assign)unsigned long long uploadOffset;
- @property (nonatomic , copy) NSString *host;
- @property (nonatomic , copy) NSString *port;
- @end
- @implementation WSUploadSession
- + (WSUploadSession *)uploadFileWithServerHost:(NSString *)host port:(NSString *)port fileMD5:(NSString *)fileMD5 uuid:(NSString *)uuid fileSize:(NSInteger)fileSize startSize:(NSInteger)startSize localFileFullPath:(NSString *)localFileFullPath processBlock:(UploadProgressBlock)processBlock successBlock:(UploadSuccessBlock)successBlock failBlock:(UploadFailedBlock)failBlock
- {
- WSUploadSession *uploadSession = [[WSUploadSession alloc]initUploadFileWithServerHost:host port:port fileMD5:fileMD5 uuid:uuid fileSize:fileSize startSize:startSize localFileFullPath:localFileFullPath processBlock:processBlock successBlock:successBlock failBlock:failBlock];
- return uploadSession;
- }
- - (id)initUploadFileWithServerHost:(NSString *)host port:(NSString *)port fileMD5:(NSString *)fileMD5 uuid:(NSString *)uuid fileSize:(NSInteger)fileSize startSize:(NSInteger)startSize localFileFullPath:(NSString *)localFileFullPath processBlock:(UploadProgressBlock)processBlock successBlock:(UploadSuccessBlock)successBlock failBlock:(UploadFailedBlock)failBlock
- {
- if (self = [super init]) {
- self.uploadProgressBlock = processBlock;
- self.uploadFailedBlock = failBlock;
- self.uploadSuccessBlock = successBlock;
-
- if ([_asyncSocket isConnected]) {
- [_asyncSocket disconnect];
- _asyncSocket.delegate = nil;
- _asyncSocket = nil;
- }
-
- _asyncSocket = [[AsyncSocket alloc] initWithDelegate:self];
- _runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes];
-
- _uploadOffset = startSize;
-
- if ([FileUtils fileSizeAtPath:localFileFullPath] < fileSize) {
-
- fileSize = [FileUtils fileSizeAtPath:localFileFullPath];
- };
-
- _fileSize = fileSize;
-
- _filePath = localFileFullPath;
-
- _fileName = localFileFullPath.lastPathComponent;
-
- _host = host;
-
- _port = port;
-
- _md5 = fileMD5;
-
- _uuid = uuid;
-
- [self operationDidStart];
- }
-
- return self;
- }
- //+ (void)networkRequestThreadEntryPoint:(id)__unused object {
- // @autoreleasepool {
- // [[NSThread currentThread] setName:@"TCPSocketUpLod"];
- // NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
- // [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
- // [runLoop run];
- // }
- //}
- //
- //+ (NSThread *)networkRequestThread {
- // static NSThread *_networkRequestThread = nil;
- // static dispatch_once_t oncePredicate;
- // dispatch_once(&oncePredicate, ^{
- // _networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
- // [_networkRequestThread start];
- // });
- // return _networkRequestThread;
- //}
- //
- //
- //
- //-(void)start
- //{
- // if ([self isCancelled]) {
- // [self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[_runLoopModes allObjects]];
- // } else if ([self isReady]) {
- // [self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[_runLoopModes allObjects]];
- // }
- //}
- //FILE_UP_SERVER_HOST FILE_UP_SERVER_PORT
- - (void)operationDidStart {
- NSError *error;
- if (![_asyncSocket connectToHost:_host onPort:[_port integerValue] error:&error])
- {
- NSLog(@"Error connecting: %@", error);
- }
- }
- #pragma mark --
- #pragma mark -- sockectOperate
- -(void)writeToSocket:(NSMutableData *)data {
- [_asyncSocket writeData:data withTimeout:-1 tag:0];
- [_asyncSocket readDataToData:[AsyncSocket JsonData] withTimeout:-1 tag:1];
- }
- #pragma mark socket delegate
- - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
- {
- NSLog(@"didConnectToHost");//通过数据包的偏移位置来控制断点上传的二进制数据 00112000231
- NSData *bitData = [self makeChunk:_uploadOffset];
-
- if (bitData) {
- [self writeToSocket:[[NSMutableData alloc]initWithData:[self makeChunk:_uploadOffset]]];
- }
-
- }
- #warning 文件上传/下载只有两种状态,取消,下载
- -(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
- //如果用户退出,如何判断消息是上次还是下载,则msg新增字段,这里为上传。
-
- DataInputStream *inputData = [DataInputStream dataInputStreamWithData:data];
- NSString *str = [inputData readUTF];
- if (!str) {
-
- [self cancerUpload];
-
- if (self.uploadFailedBlock) {
- self.uploadFailedBlock(@"error",self.uuid);
- }
-
- // if (self.uploadFailedDBBlock) {
- // self.uploadFailedDBBlock(@"error",self.uuid);
- // }
-
-
- return;
- }
-
- NSDictionary* dic = str.jsonValue;
- BOOL success = [[dic objectForKey:@"success"] boolValue];
- NSInteger code = [[dic valueForKey:@"code"] integerValue];
- if (!success) {
- NSString *errMessage = [dic objectForKey:@"message"];
- NSLog(@"message:---%@", errMessage);
- [self cancerUpload];
- if (self.uploadFailedBlock) {
- self.uploadFailedBlock(errMessage,self.uuid);
- }
-
-
-
- return;
- }
- //区分状态码的返回结果
- if (code == 304) {
-
- //
- if (self.uploadSuccessBlock) {
- self.uploadSuccessBlock(nil,_fileSize,self.md5);
-
- }
-
- // if (self.uploadSuccessDBBlock) {
- // self.uploadSuccessDBBlock(nil,_fileSize,self.md5);
- // }
- // if (self.completionBlock) {
- // self.completionBlock();
- // }
-
- //关闭连接
- [sock disconnect];
-
- return;
- }else if(code == 200){
- unsigned long long start = [[dic valueForKey:@"accept"] integerValue];
- double progress = ((double)start/_fileSize);
- if (self.uploadProgressBlock) {
- self.uploadProgressBlock(progress,start,self.uuid);
- NSLog(@"当前人物uuid--%@",self.uuid);
- }
-
- // if (self.uploadProgressDBBlock) {
- // self.uploadProgressDBBlock(progress,start,self.uuid);
- // }
- _uploadOffset = start;
- NSLog(@"已经上传%llu, 当前进度%f%%", start, progress*100);
-
- [self writeToSocket:[[NSMutableData alloc]initWithData:[self makeChunk:start]]];
- }
- }
- -(void)onSocketDidDisconnect:(AsyncSocket *)sock
- {
- NSLog(@"socketDidDisconnect");
-
- }
- -(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
- {
- NSLog(@"socketDidDisconnect with error");
-
- [self cancerUpload];
-
- if (self.uploadFailedBlock) {
- self.uploadFailedBlock(@"onSocketDidDisconnect",self.uuid);
- }
-
- }
- #pragma mark --
- #pragma mark --
- /*客户端向服务端发送文件:
-
- 本次传输的包总长度(0-4)
- +协议说明JSON长度(4-8)
- {
- "md5":"E96261B90BE7B1895E9193D9CB9AAC5A",
- "crc":"F9C19B6F",
- "cmd":"1",
- "fileName":"0483737.xls",
- "offset":0,
- "user":
- {
- "sender":"serverid-gyj","receiver":"serverid-joe"
- },
- "fileLength":83456,
- "client":
- {
- "name":"realicq",
- "version":"6.5"
- },
- "complete":1
- }
- +文件流长度(4位)+文件流
- */
- -(NSData *)makeChunk:(unsigned long long) start{
-
- NSUInteger toSendChunkSize = 0;
- if (start + ChunkSize > _fileSize) {
- toSendChunkSize = (unsigned int)(_fileSize - start);
- }else{
- toSendChunkSize = ChunkSize;
- }
- NSData *chunk = [[NSMutableData alloc] init];
-
- if (_sendData && !_filePath) {
- [self cancerUpload];
-
- if (self.uploadFailedBlock) {
- self.uploadFailedBlock(@"upload fail",self.uuid);
- }
-
-
-
- return nil;
-
-
- }else{
- NSFileHandle *readHandle = [NSFileHandle fileHandleForReadingAtPath:_filePath];
- [readHandle seekToFileOffset:start];
- if(!readHandle)
- {
- [self cancerUpload];
-
- if (self.uploadFailedBlock) {
- self.uploadFailedBlock(@"error",self.uuid);
- }
-
-
-
- return nil;
- }
-
- NSInputStream *inputStream = [NSInputStream inputStreamWithData:[readHandle readDataOfLength:toSendChunkSize]];
- [inputStream open];
-
- chunk = [[NSMutableData alloc]initWithLength:toSendChunkSize];
- NSUInteger readLength = (NSUInteger)[inputStream read:(uint8_t*)[chunk bytes] maxLength:chunk.length];
- if (readLength != [chunk length]) {
-
- [self cancerUpload];
-
- if (self.uploadFailedBlock) {
- self.uploadFailedBlock(@"error",self.uuid);
- }
-
-
-
- return nil;
- }
- [inputStream close];
- }
-
- NSString *crc32 = [NSString stringWithFormat:@"%@",[[NSString alloc] initWithFormat:@"%08x",chunk.crc32]];
-
- NSDictionary *chunkDes = nil;
-
-
- // if (self.messageType == MESSAGE_TYPE_GROUP) {
-
- chunkDes = @{
- @"md5":_md5,
- @"crc":crc32,
- @"cmd":@"1",
- @"fileName":_fileName,
- @"offset":@(start),
- @"fileLength":@(_fileSize),
- @"client":@{@"name":@"iOS",@"version":@"1.0"},
- @"complete":@(1)
- };
-
-
- NSLog(@"chunkDes: %@",chunkDes);
-
- NSString *desString=[chunkDes jsonString];
-
- DataOutputStream *outData = [DataOutputStream new];
-
- [outData writeInt:0];
- [outData writeUTF:desString];
- [outData writeBytes:chunk];
- [outData writeDataCount];
-
- NSData *sendData = [outData toByteArray];
- if(!sendData)
- {
-
- [self cancerUpload];
- if (self.uploadFailedBlock) {
-
- self.uploadFailedBlock(@"error",self.uuid);
- }
-
-
-
- }
- return sendData;
- }
- - (void)cancerUpload
- {
- // [super cancel];
-
- if (_asyncSocket.isConnected) {
- [_asyncSocket disconnect];
- _asyncSocket.delegate = nil;
- _asyncSocket = nil;
- }
-
-
-
- }
- - (void)resumeUpload
- {
-
-
- }
- @end
|