iOS 通讯之FTP

作者: NextStepPeng | 来源:发表于2019-07-16 15:12 被阅读0次

背景

因项目需要,需要在规定的时间内根据特定的信号,将大量的图片和文件下载/上传到iOS本地/服务器进行实时渲染,因之前也尝试了socket通讯,但还是会引起通讯阻塞(因还有大量接口需要采用socket通讯)。故采用FTP协议传输。

FTP

FTP(File Transfer Protocol,文件传输协议) 是 TCP/IP 协议组中的协议之一。FTP协议包括两个组成部分,其一为FTP服务器,其二为FTP客户端。FTP允许用户以文件操作的方式(如文件的增、删、改、查、传送等)与另一主机相互通信

联调工具

  • 推荐使用工具: FileZilla
  • 也可以用终端ssh指令,将特定的文件上传/下载到FTP服务器,做完辅助测试用
    上传
scp "需要上传的文件" root@182.168.1.88:/home/pi/App

下载,先登录到远程设备(我这边是Linux系统服务器)

scp "需要下载的文件" root@182.168.1.3:/Users/peng***/Documents/1-21

FTP传输

因我这边项目需要只需要上传和下载文件(登录每次请求的时候携带用户名和密码),故FTP的其它功能没有封装(采用CFWiterRef),大同小异。

  • 上传
 CFWriteStreamRef writeStreamRef = CFWriteStreamCreateWithFTPURL(NULL, ( __bridge CFURLRef) url);
//url :上传的地址
        CFWriteStreamSetProperty(writeStreamRef,
                                 kCFStreamPropertyFTPAttemptPersistentConnection,
                                 kCFBooleanFalse);
        
        CFWriteStreamSetProperty(writeStreamRef, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
        CFWriteStreamSetProperty(writeStreamRef, kCFStreamPropertyFTPUsePassiveMode, kCFBooleanTrue);
        CFWriteStreamSetProperty(writeStreamRef, kCFStreamPropertyFTPFetchResourceInfo, kCFBooleanTrue);
        CFWriteStreamSetProperty(writeStreamRef, kCFStreamPropertyFTPUserName, (__bridge CFStringRef) self.ftpUsername);
        CFWriteStreamSetProperty(writeStreamRef, kCFStreamPropertyFTPPassword, (__bridge CFStringRef) self.ftpPassword);
        
        self.commandStream = ( __bridge_transfer NSOutputStream *) writeStreamRef;
//得到输出流
        
        self.commandStream.delegate = self;
        [self performSelector:@selector(scheduleInCurrentThread:)
                     onThread:[[self class] networkThread]
                   withObject:self.commandStream
                waitUntilDone:YES];
        
        [self.commandStream open]
  • 下载
CFReadStreamRef readStreamRef = CFReadStreamCreateWithFTPURL(NULL, ( __bridge CFURLRef) url);
        CFReadStreamSetProperty(readStreamRef,
                                kCFStreamPropertyFTPAttemptPersistentConnection,
                                kCFBooleanFalse);
        
        CFReadStreamSetProperty(readStreamRef, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
        CFReadStreamSetProperty(readStreamRef, kCFStreamPropertyFTPUsePassiveMode, kCFBooleanTrue);
        CFReadStreamSetProperty(readStreamRef, kCFStreamPropertyFTPFetchResourceInfo, kCFBooleanTrue);
        CFReadStreamSetProperty(readStreamRef, kCFStreamPropertyFTPUserName, (__bridge CFStringRef) self.ftpUsername);
        CFReadStreamSetProperty(readStreamRef, kCFStreamPropertyFTPPassword, (__bridge CFStringRef) self.ftpPassword);
        //
        CFReadStreamSetProperty(readStreamRef, kCFStreamPropertyFTPProxy, kCFBooleanTrue);
        //
        
        self.dataStream = ( __bridge_transfer NSInputStream *) readStreamRef;
        self.dataStream.delegate = self;
        if (self.dataStream == nil) {
            
            [self.delegate ftpError:self withErrorCode:FTPClientCantReadStream];
            
        }
        
        [self performSelector:@selector(scheduleInCurrentThread:)
                     onThread:[[self class] networkThread]
                   withObject:self.dataStream
                waitUntilDone:YES];
       
//        [self.dataStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

        [self.dataStream open];
  • 输入输出流回调处理
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
// An NSStream delegate callback that's called when events happen on our
// network stream.
{
#pragma unused(aStream)
     switch (eventCode) {
        case NSStreamEventOpenCompleted: {
            self.didOpenStream = true;
            if ([self.currentOperation isEqualToString:@"GET"]){
                self.maximumSize = [[aStream propertyForKey:(id)kCFStreamPropertyFTPResourceSize] integerValue];
                //NSLog(@"%luself.maximumSize:%d: %f",self.dType,self.currentIndex,self.maximumSize );
            }
            self.uploadBytesTotal = 0;
            self.bytesRemaining = 0;
            self.bytesTotal = 0;
        } break;
        case NSStreamEventHasBytesAvailable: {
            if ([self.currentOperation isEqualToString:@"GET"]){
               
               NSData *data = [self read];
               if (data) {
                  [self.receivedData appendData:data];
               }else {
                   NSLog(@"流出现异常");
                   [self.delegate ftpError:self withErrorCode:FTPClientCantReadStream];
                   [self closeAll];
               }
            }
        } break;

        case NSStreamEventHasSpaceAvailable: {
                if (self.bytesRemaining == 0) {
                    self.sentData = [NSData dataWithContentsOfFile:self.uploadFilePath];
                    
                    self.bytesRemaining = [_sentData length];
                    self.bytesIndex = 0;
                    
                    if (self.sentData == nil) {
                        [self.delegate ftpUploadFinishedWithSuccess:self];
                    }
                    
                }
                NSUInteger nextPackageLength = MIN(kGRDefaultBufferSize, self.bytesRemaining);
                NSRange range = NSMakeRange(self.bytesIndex, nextPackageLength);
            
                NSData *packetToSend = [self.sentData subdataWithRange: range];
            
                [self uploadWrite:packetToSend];
            
                self.bytesIndex += self.bytesThisIteration;
                self.bytesRemaining -= self.bytesThisIteration;
            
            
        } break;
        case NSStreamEventErrorOccurred: {
            
            [self.delegate ftpError:self withErrorCode:FTPClientCantOpenStream];
            
            [self closeAll];
        } break;
        case NSStreamEventEndEncountered: {
            // ignore
            if ([self.currentOperation isEqualToString:@"GET"]){
                //NSLog(@"%luself.maximumSizeEnd:%d:%.2f",(unsigned long)self.dType,self.currentIndex,self.maximumSize );
                //NSLog(@"%luself.maximumSizeData:%d:%lu",(unsigned long)self.dType,self.currentIndex,self.receivedData.length );
                if (self.maximumSize != self.receivedData.length) {
                    //下载异常
                    NSLog(@"下载异常:%d",self.currentIndex);
                    [self.delegate ftpError:self withErrorCode:FTPClientCantOpenStream];
                    
                    [self closeAll];
                    return;
                }
                if ([self downOk]) {
                    if ([self.delegate respondsToSelector:@selector(ftpDownloadFinishedWithSuccess:withIndex:withPath:withData:)]) {
                     
                        [self.delegate ftpDownloadFinishedWithSuccess:self withIndex:self.currentIndex withPath:self.localname withData:self.receivedData];
                    }
                    
                }
                
                
                [self closeAll];
            }
            if ([self.currentOperation isEqualToString:@"upload"]) {
                [self.delegate ftpError:self withErrorCode:FTPClientCantOpenStream];
                [self closeAll];
            }
        } break;
        default: {
            assert(NO);
        } break;
    }
}
  • 这个demo里面异常处理以及流处理中都用到了RunLoop处理RunLoop 说明

demo

相关文章

  • iOS 通讯之FTP

    背景 因项目需要,需要在规定的时间内根据特定的信号,将大量的图片和文件下载/上传到iOS本地/服务器进行实时渲染,...

  • ReactNative与iOS的混编

    ReactNative与iOS的混编 通讯 ReactNative与iOS的通讯这里头很详细 嵌入 iOS原生调用...

  • iOS 之FTP上传 文件

    在日常开发中,我们都在用http(s) 来进行网络传输的,上传下载等任务的,前段时间听说要用ftp来上传资源,当时...

  • 第三方聊天方案选择

    2018.4.21 现在市面上有多少方案可以选择? 方案一:socket通信 iOS开发之即时通讯之Socket(...

  • iOS FTP上传

    ftp简介 什么是ftp 在iOS端的ftp上传使用的是CFNetWork框架,它处于核心服务框架中,提供了一个抽...

  • 【转】iOS开发之蓝牙通信

    iOS开发之蓝牙通讯 一、引言 蓝牙是设备近距离通信的一种方便手段,在iPhone引入蓝牙4.0后,设备之间的通讯...

  • iOS 长连接资料

    iOS即时通讯,从入门到“放弃”?iOS即时通讯进阶 - CocoaAsyncSocket源码解析(Connect...

  • iOS9.0之前和之后获取通讯录的方法

    1. iOS 9.0之前获取通讯录的方法 打印结果: 2. iOS 9.0 及 iOS 9.0之后获取通讯录的方法...

  • File Services之文件共享服务FTP

    文件共享服务之FTP FTP:File transfer protocol FTP的传输使用的是TCP协议,是一种...

  • 探索 messageHandler 的传输性能极限

    本次测试的目标是 iOS 8+ 之后提供的 WKWebview 提供的 JS 和 Native 通讯机制之 mes...

网友评论

    本文标题:iOS 通讯之FTP

    本文链接:https://www.haomeiwen.com/subject/fevzkctx.html