IOS ARC模式下利用FTP进行图片下载的详解
2017-05-16 11:38
288 查看
近日公司提出一个需要从FTP下载图片到本地的一个需求,之前一直是通过http的方式来下载图片,这次用到了FTP,这几天通过对FTP的研究,整理出了一些心得和写了一个demo.提供给初学的小伙伴进行参考.
直接在Bulid Phases中的Link Binary With Librarise中添加即可
这里重点是要遵循NSStreamDelegate协议,其他事一些页面UI的按钮输入框,小伙伴们可以自行定义UI.
然后我们再到我们的.m文件里面,在点击按钮要触发下载的方法
这里需要注意的是,账号和密码是你FTP服务器的账号和密码,url的地址里面你要注意,如果公司没有改FTP的端口的话默认是80端口,如果公司该了FTP的端口号,在你的url上必须加上你的端口号,比如ftp://fpt.test.com:60001
接着实现NSStreamDelegate委托方法,里面有一些判断和错误
以上两个方法包含了对于结果的处理时,需要关闭连接的方法- (void)_stopReceiveWithStatus:(NSString *)statusString,并且bytesWritten是实际写入的数据,每次写入的数据不固定,因此需要bytesWrittenSoFar变量来定位到上次写入数据的位置。
理论
ios的FTP下载使用的是CFNetwork框架,他提供了一个抽象化的网络协议库.使用该框架中的CFFTPStream我们可以进行FTP上的基本操作,比如:上传,下载,创建远程目录,但是也不是支持所有的FTP操作,比如删除文件,重命名文件,自定义FTP命令等复杂操作无法完成.需要导入的依赖库
在我们进行代码编写之前,我们新建一个工程,这里就不详细叙述,建好之后,我们导入以下依赖库.如图:直接在Bulid Phases中的Link Binary With Librarise中添加即可
主要代码
首先在我们自己的控制器的.h文件里,添加如下代码:#import <UIKit/UIKit.h> @interface WKViewController : UIViewController <UITextFieldDelegate,NSStreamDelegate> @property (strong, nonatomic) IBOutlet UITextField *serverInput; @property (strong, nonatomic) IBOutlet UILabel *status; @property (strong, nonatomic) IBOutlet UIImageView *imageView; - (IBAction)downLoadAction:(id)sender; - (IBAction)didEndEditing:(id)sender; @end
这里重点是要遵循NSStreamDelegate协议,其他事一些页面UI的按钮输入框,小伙伴们可以自行定义UI.
然后我们再到我们的.m文件里面,在点击按钮要触发下载的方法
- (IBAction)downLoadAction:(id)sender { CFReadStreamRef ftpStream; NSURL *url; //获得地址 url =[NSURL URLWithString:_serverInput.text]; NSString *account = Your_FTP_Account;//_accountInput.text; NSString *password = Your_FTP_Password;//_passwordInput.text; NSLog(@"url is %@",url); //这是本地电脑的路径 // self.filePath = @"/Users/dev/Desktop/test.jpg"; //这是手机沙盒路径 NSString *path_document = NSHomeDirectory(); //设置一个图片的存储路径 self.filePath = [path_document stringByAppendingString:[NSString stringWithFormat:@"/Documents/%@",[[NSUserDefaults standardUserDefaults]objectForKey:@"filename"]]]; self.fileStream = [NSOutputStream outputStreamToFileAtPath:self.filePath append:NO]; [self.fileStream open]; // 打开CFFTPStream ftpStream = CFReadStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) url); self.networkStream = (__bridge NSInputStream *) ftpStream; assert(ftpStream != NULL); //设置ftp账号密码 [self.networkStream setProperty:account forKey:(id)kCFStreamPropertyFTPUserName]; [self.networkStream setProperty:password forKey:(id)kCFStreamPropertyFTPPassword]; // 设置代理 self.networkStream.delegate = self; // 启动循环 [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [self.networkStream open]; CFRelease(ftpStream); }
这里需要注意的是,账号和密码是你FTP服务器的账号和密码,url的地址里面你要注意,如果公司没有改FTP的端口的话默认是80端口,如果公司该了FTP的端口号,在你的url上必须加上你的端口号,比如ftp://fpt.test.com:60001
接着实现NSStreamDelegate委托方法,里面有一些判断和错误
#pragma mark NSStreamDelegate委托方法 - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{ switch (eventCode) { case NSStreamEventOpenCompleted: { } break; case NSStreamEventHasBytesAvailable: { NSInteger bytesRead; uint8_t buffer[32768];//缓冲区的大小 32768可以设置,uint8_t为一个字节大小的无符号int类型 // 读取数据 bytesRead = [self.networkStream read:buffer maxLength:sizeof(buffer)]; if (bytesRead == -1) { [self _stopReceiveWithStatus:@"读取网络数据出错"]; } else if (bytesRead == 0) { //下载成功 [self _stopReceiveWithStatus:nil]; } else { NSInteger bytesWritten;//实际写入数据 NSInteger bytesWrittenSoFar;//当前数据写入位置 // 写入文件 bytesWrittenSoFar = 0; do { bytesWritten = [self.fileStream write:&buffer[bytesWrittenSoFar] maxLength:bytesRead - bytesWrittenSoFar]; assert(bytesWritten != 0); if (bytesWritten == -1) { [self _stopReceiveWithStatus:@"文件写入出错"]; assert(NO); break; } else { bytesWrittenSoFar += bytesWritten; } } while (bytesWrittenSoFar != bytesRead); } } break; case NSStreamEventHasSpaceAvailable: { assert(NO); } break; case NSStreamEventErrorOccurred: { [self _stopReceiveWithStatus:@"打开出错,请检查路径"]; assert(NO); case NSStreamEventEndEncountered: { } break; default: assert(NO); break; } } } #pragma mark 结果处理,关闭链接 - (void)_stopReceiveWithStatus:(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; } if(statusString == nil){ statusString = @"下载成功"; _imageView.image = [UIImage imageWithContentsOfFile:self.filePath]; } self.status.text = statusString; self.filePath = nil; }
以上两个方法包含了对于结果的处理时,需要关闭连接的方法- (void)_stopReceiveWithStatus:(NSString *)statusString,并且bytesWritten是实际写入的数据,每次写入的数据不固定,因此需要bytesWrittenSoFar变量来定位到上次写入数据的位置。
以上就是关于IOS FTP的下载图片一些比较核心的内容,以及开发过程中需要注意的几个点,另外我已经将写好的demo上传了GitHub,大家可以去我的git上下载已经写好的代码:https://github.com/WJeaner/AppFTPdownLoad.git
转载请注明出处,违者必究!相关文章推荐
- 利用Apache commons-net 包进行FTP文件和文件夹的上传与下载
- 利用SecureCRT在windows与linux服务器之间利用ftp进行文件的上传下载
- swift 网络----利用URLSession的Block模式下载多张图片
- 利用NSOperation进行异步图片下载——设置UITabView数据,图片下载,占位图。解决异步下载和Cell重用造成的图片设置混乱。和多次重复下载的问题
- swift 网络----利用URLSession的Download Task模式下载多张图片
- IOS ARC模式下图片上传到FTP的详解
- 利用curl进行ftp的下载和上传
- 详解Swift 利用Opration和OprationQueue来下载网络图片
- 一切尽在自动中(二),sqlserver “利用FTP下载然后bcp方式导入数据到数据库”
- 利用图片进行定位
- 利用图片进行定位
- Asp.net中图片存储数据库以及页面读取显示通用方法详解-附源码下载
- 使用API进行FTP文件上传和下载
- 利用vc++中的winInet进行网络编程实现了下载网站的源代码
- 利用IDhttp实现图片下载
- Flex 中利用Matrix 类的rotate函数对图片进行旋转操作的例子
- Flex中如何利用Matrix类的rotate函数对图片进行旋转操作的例子
- 使用wininet进行FTP文件上传和下载
- FTP模式详解
- 利用API在FTP服务器上上传和下载文件