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

本文介绍了一种在iOS应用中通过FTP协议下载图片的方法。利用CFNetwork框架中的CFFTPStream,实现了FTP的基本操作,包括账号密码设置、数据读取与文件写入,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

近日公司提出一个需要从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

转载请注明出处,违者必究!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值