美文网首页
iOS FTP上传

iOS FTP上传

作者: 于是有了涛 | 来源:发表于2016-11-12 20:50 被阅读2555次

    ftp简介

    什么是ftp

    在iOS端的ftp上传使用的是CFNetWork框架,它处于核心服务框架中,提供了一个抽象化的网络协议库。使用CFNetWork框架中的CFFTPStream类提供的API能够做很多ftp操作,例如上传文件、下载文件、下载目录列表,创建远程目录等等。

    但是在使用上也存在一些的限制,CFFTPStream 提供的ftp操作比较基础,它并不是完全的FTP客户端API,不支持所有的FTP操作。
    例如:

    FTPS(FTP over TLS)
    删除文件(没法像Android里面的comment-net包那样可以直接删除服务器文件)
    重命名文件
    自定义FTP命令
    另外,CFFTPStream的目录解析也局限于简单的目录,只能够解析一般的基于UNIX FTP服务的目录。

    配置

    要使用CFFTPStream的功能,需要导入CFNetWork 框架,方便的是不用去下载第三方包,直接在Xcode里面添加就好了。

    1)添加CFNetWork framework

    2)新建工程 使用Storyboard拖拽控件

    协议

    这里需要遵循 NSStreamDelegate

    代码演示

    pragma mark 上传事件

    • (IBAction)sendAction:(id)sender {

    NSURL *url;//ftp服务器地址
    NSString *filePath;//图片地址
    NSString *account;//账号
    NSString *password;//密码
    CFWriteStreamRef ftpStream;

    //获得输入
    url = [NSURL URLWithString:_serverInput.text];
    filePath = _fileInput.text;
    account = _accountInput.text;
    password = _passwordInput.text;

    //添加后缀(文件名称)
    url = [NSMakeCollectable(CFURLCreateCopyAppendingPathComponent(NULL, (CFURLRef) url, (CFStringRef) [filePath lastPathComponent], false)) autorelease];

    //读取文件,转化为输入流
    self.fileStream = [NSInputStream inputStreamWithFileAtPath:filePath];
    [self.fileStream open];

    //为url开启CFFTPStream输出流
    ftpStream = CFWriteStreamCreateWithFTPURL(NULL, (CFURLRef) url);
    self.networkStream = (NSOutputStream *) ftpStream;

    //设置ftp账号密码
    [self.networkStream setProperty:account forKey:(id)kCFStreamPropertyFTPUserName];
    [self.networkStream setProperty:password forKey:(id)kCFStreamPropertyFTPPassword];

    //设置networkStream流的代理,任何关于networkStream的事件发生都会调用代理方法
    self.networkStream.delegate = self;

    //设置runloop
    [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [self.networkStream open];

    //完成释放链接
    CFRelease(ftpStream);
    }

    pragma mark 回调方法

    • (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
      {
      //aStream 即为设置为代理的networkStream
      switch (eventCode) {
      case NSStreamEventOpenCompleted: {
      NSLog(@"NSStreamEventOpenCompleted");
      } break;
      case NSStreamEventHasBytesAvailable: {
      NSLog(@"NSStreamEventHasBytesAvailable");
      assert(NO); // 在上传的时候不会调用
      } break;
      case NSStreamEventHasSpaceAvailable: {
      NSLog(@"NSStreamEventHasSpaceAvailable");
      NSLog(@"bufferOffset is %zd",self.bufferOffset);
      NSLog(@"bufferLimit is %zu",self.bufferLimit);
      if (self.bufferOffset == self.bufferLimit) {
      NSInteger bytesRead;
      bytesRead = [self.fileStream read:self.buffer maxLength:kSendBufferSize];

    if (bytesRead == -1) {
    //读取文件错误
    [self _stopSendWithStatus:@"读取文件错误"];
    } else if (bytesRead == 0) {
    //文件读取完成 上传完成
    [self _stopSendWithStatus:nil];
    } else {
    self.bufferOffset = 0;
    self.bufferLimit = bytesRead;
    }
    }

    if (self.bufferOffset != self.bufferLimit) {
    //写入数据
    NSInteger bytesWritten;//bytesWritten为成功写入的数据
    bytesWritten = [self.networkStream write:&self.buffer[self.bufferOffset] maxLength:self.bufferLimit - self.bufferOffset];
    assert(bytesWritten != 0);
    if (bytesWritten == -1) {
    [self _stopSendWithStatus:@"网络写入错误"];
    } else {
    self.bufferOffset += bytesWritten;
    }
    }
    } break;
    case NSStreamEventErrorOccurred: {
    [self _stopSendWithStatus:@"Stream打开错误"];
    assert(NO);
    } break;
    case NSStreamEventEndEncountered: {
    // 忽略
    } break;
    default: {
    assert(NO);
    } break;
    }
    }

    //结果处理

    • (void)_stopSendWithStatus:(NSString *)statusString
      {
      if (self.networkStream != nil) {
      [self.networkStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
      self.networkStream.delegate = nil;
      [self.networkStream close];
      self.networkStream = nil;
      }
      if (self.fileStream != nil) {
      [self.fileStream close];
      self.fileStream = nil;
      }
      [self _sendDidStopWithStatus:statusString];
      }

    • (void)_sendDidStopWithStatus:(NSString *)statusString
      {
      if (statusString == nil) {
      statusString = @"上传成功";
      }
      _status.text = statusString;
      }

    //输入Done事件
    -(IBAction)textFieldDoneEditing:(id)sender{
    [sender resignFirstResponder];
    }

    pragma mark UITextField代理方法

    -(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
    [UIView beginAnimations:@"ResignForKeyBoard" context:nil];
    [UIView setAnimationDuration:0.30f];

    CGRect rect = CGRectMake(0.0f, -10.0f, self.view.frame.size.width, self.view.frame.size.height);
    self.view.frame = rect;

    [UIView commitAnimations];
    return YES;
    }

    -(BOOL)textFieldShouldEndEditing:(UITextField *)textField{
    [UIView beginAnimations:@"ResignForKeyBoard" context:nil];
    [UIView setAnimationDuration:0.30f];

    CGRect rect = CGRectMake(0.0f, 20.0f, self.view.frame.size.width, self.view.frame.size.height);
    self.view.frame = rect;

    [UIView commitAnimations];
    return YES;
    }

    相关文章

      网友评论

          本文标题: iOS FTP上传

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