上一篇文章分析了ftp的上传原理,本文接着介绍ftp的下载,ftp下载使用的是Anonymous FTP ,即匿名的ftp,可以用它下载一些公共的文件,而不需要输入账号密码。
【传送门】:iOS ftp上传
http://blog.csdn.net/yang8456211/article/details/12451013
在iOS端的ftp下载使用的也是CFNetWork框架中的CFFTPStreamAPI,不赘述了,在iOS ftp上传里面有较细的描述。
1) 建立SingleView项目,取名为FtpDownLoad,导入CFNetWork 框架。
第一步:
第二步:
2) 配置nib文件
包括:
当下载完成之后,我们会用从本地读取图片显示。
#import <UIKit/UIKit.h> @interface YGViewController : UIViewController <UITextFieldDelegate,NSStreamDelegate> @property (retain, nonatomic) IBOutlet UITextField *serverInput; @property (retain, nonatomic) IBOutlet UILabel *status; @property (retain, nonatomic) IBOutlet UIImageView *imageView; - (IBAction)downLoadAction:(id)sender;//下载事件 - (IBAction)didEndEditing:(id)sender;//关闭键盘 @end
使用CFFTPStream进行下载,首先要遵循NSStreamDelegate协议。并实现协议中的委托方法。
下面为NSStreamDelegate协议的内容。
@protocol NSStreamDelegate <NSObject>
@optional
- (void)stream:(NSStream *)aStreamhandleEvent:(NSStreamEvent)eventCode;
@end
参数:
aStream
The stream on which eventCode occurred.(即委托的Stream,任何关于此Stream的事件发生都会调用此方法)
eventCode
The stream event that occurred(Stream发生的事件,例如打开、传输数据等)
声明变量与getter、setter
@interface YGViewController () //声明内部变量 @property (nonatomic, retain) NSInputStream * networkStream;//输入流 @property (nonatomic, copy) NSString * filePath;//文件路径 @property (nonatomic, retain) NSOutputStream * fileStream;//输出流 @end //getter、setter @implementation YGViewController @synthesize serverInput = _serverInput; @synthesize status = _status; @synthesize imageView = _imageView;
点击下载触发的事件
#pragma mark 点击下载按钮 - (IBAction)downLoadAction:(id)sender { CFReadStreamRef ftpStream; NSURL *url; //获得地址 url = [NSURL URLWithString:_serverInput.text]; NSLog(@"url is %@",url); // 为文件存储路径打开流,filePath为文件写入的路径,hello为图片的名字,具体可换成自己的路径 self.filePath = @"/Users/yangguang/Desktop/hello.png"; self.fileStream = [NSOutputStream outputStreamToFileAtPath:self.filePath append:NO]; [self.fileStream open]; // 打开CFFTPStream ftpStream = CFReadStreamCreateWithFTPURL(NULL, (CFURLRef) url); self.networkStream = (NSInputStream *) ftpStream; assert(ftpStream != NULL); // 设置代理 self.networkStream.delegate = self; // 启动循环 [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [self.networkStream open]; //释放链接 CFRelease(ftpStream); }
self.networkStream.delegate =self;的意思是设置networkStream为NSStreamDelegate协议中的代理,即回调方法中的“aStream”。
关于delegate的介绍请看:http://blog.csdn.net/yang8456211/article/details/11542455
回调方法:
#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; } } }
bytesWritten是实际写入的数据,每次写入的数据不固定,因此需要bytesWrittenSoFar变量来定位到上次写入数据的位置。
结果处理:
关闭链接,从filePath中读取图片信息并显示。
#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; }
http://download.csdn.net/detail/yang8456211/6374441
atany原创,转载请注明博主与博文链接,未经博主允许,禁止任何商业用途。
博文地址:http://blog.csdn.net/yang8456211/article/details/12524669
博客地址:http://blog.csdn.net/yang8456211
—— by atany