您的位置:首页 > 移动开发 > IOS开发

IOS ARC模式下利用FTP进行图片下载的详解

2017-05-16 11:38 288 查看
近日公司提出一个需要从FTP下载图片到本地的一个需求,之前一直是通过http的方式来下载图片,这次用到了FTP,这几天通过对FTP的研究,整理出了一些心得和写了一个demo.提供给初学的小伙伴进行参考.

理论

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

转载请注明出处,违者必究!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: