iOS 之FTP上传 文件

在日常开发中,我们都在用http(s) 来进行网络传输的,上传下载等任务的,前段时间听说要用ftp来上传资源,当时还是一脸懵逼的。后来东拼西凑的算是勉强搞定了。

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


其实ftp无非就是一个文件流的读写操作而已,NSInputStream 和 NSOutputStream 这两个操作而已。

>>1、NSInputStream,文件输入流 

NSInputStream *inputStream = [[NSInputStream alloc] initWithFileAtPath:path]; 此处的path 为文件地址,通过该地址获取一个二进制文件信息

inputStream.delegate = self;        //// 设置代理

    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];        //// 加入到对应的runloop中

    [inputStream open];        //// 打开文件流

//// 对应的回调方法

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {

//// NSStreamEvent 是回调的类型判断。NSStreamEventOpenCompleted 表示链接成功

/// NSStreamEventHasBytesAvailable  读取数据

            uint8_t buf[1024];

            unsigned int len = 0;

            len = (int)[(NSInputStream *)aStream read:buf maxLength:1024];  // 读取数据

- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len; /// 这个方法返回实际读取的大小

            [inputData appendBytes:(const void *)buf length:len];

/// 到此处即可以把数据读取到 inputData 中

///  NSStreamEventEndEncountered 读取完成,,读取完成后需要移除操作文件流

            [aStream close];

            [aStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

            aStream = nil;

}

>>2、NSOutputStream,文件输出流 

    NSURL *url = [NSURL URLWithString:@"ftp://202.105.45.22/defaultPath/testPath/"];

    NSString *account =@"testUsername";

    NSString *password =@"testPassword";

NSOutputStream *outputStream = CFBridgingRelease(CFWriteStreamCreateWithFTPURL(NULL,(__bridge CFURLRef) url));

[outputStream setProperty:account forKey:(NSString *)kCFStreamPropertyFTPUserName];        /// 设置 username

    [outputStream setProperty:password forKey:(NSString *)kCFStreamPropertyFTPPassword];        /// 设置 password

[outputStream setProperty:kCFBooleanFalse forKey:(NSString *)kCFStreamPropertyFTPAttemptPersistentConnection];   /// 保证多次链接可实现

[outputStream setProperty:kCFBooleanFalse forKey:(NSString *)kCFStreamPropertyFTPUsePassiveMode];  //设置链接模式(主动、被动)(默认被动)

/// 设置代理,添加到对应的runloop ,打开

outputStream.delegate = self;

    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [outputStream open];

/// 然后待代理回调中 的 NSStreamEventHasSpaceAvailable下面实现 直到回掉 NSStreamEventEndEncountered 表示操作完成

            uint8_t *readBytes = (uint8_t *)[inputData mutableBytes];

            readBytes += byteIndex;

            int data_len = (int)[inputData length];

            unsigned int len = (data_len - byteIndex >= 1024) ? 1024 : (data_len - byteIndex);

            uint8_t buf[len];

            (void)memcpy(buf, readBytes, len);

            len = (int)[(NSOutputStream *)aStream write:(const uint8_t *)buf maxLength:len];

/// - (NSInteger)write:(const uint8_t *)buffer maxLength:(NSUInteger)len; 这个方法返回实际写入多少数据

            if (len == -1) {  

                     NSLog(@"写入错误!!!!");

            } else if (len == 0){  

                    NSLog(@"写入完成");  

            }

            byteIndex += len;


其实有一个很好的开源框架,( FTPManager ),使用很简单。

下面直接附上代码

//初始化文件传输管理

- (void)initFTPMgr {

        username = @"appftp";

        password = @"Appftp123";

        hostname = @"101.101.101.101";

        self.requestsManager = [[GRRequestsManager alloc] initWithHostname:hostname  user:username password:password];

//设置代理

        self.requestsManager.delegate = self;

}

//创建图片文件夹

- (void)createImagePathWithPath {

    //创建image文件夹

    NSString *imageDir = [NSString stringWithFormat:@"/%@/%@/image",self.baseFileDir,self.baseDateStr];

    [self.requestsManager addRequestForCreateDirectoryAtPath:imageDir];

    [self.requestsManager startProcessingRequests];

    NSLog(@"图片文件夹路径 %@",imageDir);

}

//准备上传文件

- (void)uploadImageWithPath:(NSURL *)url {

    NSString *pathExtension = [url pathExtension];

    self.uploadName = [NSString stringWithFormat:@"%@.%@",self.guidStr,pathExtension];

//本地文件路径

 NSString *path = url.path;

//服务器文件路径

    NSString *toPath = [NSString stringWithFormat:@"%@/%@/image/%@",self.baseFileDir,self.baseDateStr,self.uploadName];

    NSLog(@"path = %@ \n toPath = %@",path,toPath);

    NSData *data = [NSData dataWithContentsOfFile:path];

    NSLog(@"%ld",data.length);

    if (data.length > 0) {

//执行上传文件

        [self.requestsManager addRequestForUploadFileAtLocalPath:path toRemotePath:toPath];

        [self.requestsManager startProcessingRequests];

    }

}


#pragma mark -- GRRequestsManagerDelegate    //代理方法

// 完成回调

- (void)requestsManager:(id)requestsManager didCompleteUploadRequest:(id)request

{

    //请求工作流接口

    [self requestsUploadSuccess];

    NSLog(@"requestsManager:didCompleteUploadRequest:");

}

/** 进度条回传 */

- (void)requestsManager:(id)requestsManager didCompletePercent:(float)percent forRequest:(id)request

{

    if (self.uploadProgress) {

        self.uploadProgress(percent);

    }

}

//失败回调

- (void)requestsManager:(id)requestsManager didFailWritingFileAtPath:(NSString *)path forRequest:(id)request error:(NSError *)error

{

    NSLog(@"requestsManager:didFailWritingFileAtPath:forRequest:error: \n %@", error);

}

- (void)requestsManager:(id)requestsManager didFailRequest:(id)request withError:(NSError *)error

{

    NSLog(@"requestsManager:didFailRequest:withError: \n %@", error);

}


最后附上我感觉好用的FTP库( KLFTPHeper )

你可能感兴趣的:(iOS 之FTP上传 文件)