iOS中的FTPStream

这两天研究了一下iOS中的 FTP文件传送。主要参考了 官方的demo 地址是:https://developer.apple.com/library/ios/samplecode/SimpleFTPSample/Introduction/Intro.html

需要引入 CFNetwork.framework

#include <sys/socket.h>
#include <sys/dirent.h>
#include <CFNetwork/CFNetwork.h>

用到NSStream的子类,NSInputStream(读流) 和NSOutputStream(写流) 用来接收和发送数据。

以demo中的 从服务器中get到一个 图片为例

首先创建一个inputstream,用来读服务器中图片的数据。

    self.networkStream = CFBridgingRelease(
                                           CFReadStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) url)//url为ftp://....
                                           );

   [self.networkStream setProperty:@"hlct" forKey:(id)kCFStreamPropertyFTPUserName];//服务器的userName
   [self.networkStream setProperty:@"hlct2014" forKey:(id)kCFStreamPropertyFTPPassword];//密码
   
   self.networkStream.delegate = self;
   [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
   [self.networkStream open];
 

然后创建一个outstream, 把用inputstream读到的数据,写到沙盒中。

       self.fileStream = [NSOutputStream outputStreamToFileAtPath:self.filePath append:NO];
       [self.fileStream open];

接收到的 数据写在delegate中。

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
    // An NSStream delegate callback that's called when events happen on our 
    // network stream.
{
    #pragma unused(aStream)
    assert(aStream == self.networkStream);

    switch (eventCode) {
        case NSStreamEventOpenCompleted: {//链接完成
            [self updateStatus:@"Opened connection"];
        } break;
        case NSStreamEventHasBytesAvailable: { //接收到内容的时候
            NSInteger       bytesRead;
            uint8_t         buffer[32768];

            [self updateStatus:@"Receiving"];

            // Pull some data off the network.

            bytesRead = [self.networkStream read:buffer maxLength:sizeof(buffer)];
            if (bytesRead == -1) {etwork read error"];
            } else if (bytesRead == 0) {//完成
                [self stopReceiveWithStatus:nil了];
            } else {
                NSInteger   bytesWritten;
                NSInteger   bytesWrittenSoFar;

//                 Write to the file.

                bytesWrittenSoFar = 0;
                do {
                    bytesWritten = [self.fileStream write:&buffer[bytesWrittenSoFar] maxLength:(NSUInteger) (bytesRead - bytesWrittenSoFar)];
                    assert(bytesWritten != 0);
                    if (bytesWritten == -1) {
                        [self stopReceiveWithStatus:@"File write error"];
                        break;
                    } else {
                        bytesWrittenSoFar += bytesWritten;
                    }
                } while (bytesWrittenSoFar != bytesRead);
            }
        } break;
        case NSStreamEventHasSpaceAvailable: { //向服务器中写文件时,写到此处
            assert(NO);     // should never happen for the output stream
        } break;
        case NSStreamEventErrorOccurred: { //链接出错
            [self stopReceiveWithStatus:@"Stream open error"];
        } break;
        case NSStreamEventEndEncountered: {
            // ignore
        } break;
        default: {
            assert(NO);
        } break;
    }

如果是查看文件列表的时候, 用NSMutableData来接收数据。然后对数据进行下面的解析

- (void)parseListData
{
    NSMutableArray *    newEntries;
    NSUInteger          offset;

    newEntries = [NSMutableArray array];
    assert(newEntries != nil);
    
    offset = 0;
    do {
        CFIndex         bytesConsumed;
        CFDictionaryRef thisEntry;
        
        thisEntry = NULL;
        
        assert(offset <= [self.listData length]);
        //解析讲data转换成 CFDictionaryRef
        bytesConsumed = CFFTPCreateParsedResourceListing(NULL, &((const uint8_t *) self.listData.bytes)[offset], (CFIndex) ([self.listData length] - offset), &thisEntry);
        if (bytesConsumed > 0) {

            // It is possible for CFFTPCreateParsedResourceListing to return a
            // positive number but not create a parse dictionary.  For example,
            // if the end of the listing text contains stuff that can't be parsed,
            // CFFTPCreateParsedResourceListing returns a positive number (to tell
            // the caller that it has consumed the data), but doesn't create a parse
            // dictionary (because it couldn't make sense of the data).  So, it's
            // important that we check for NULL.

            if (thisEntry != NULL) {
                NSDictionary *  entryToAdd;

                entryToAdd = [self entryByReencodingNameInEntry:(__bridge NSDictionary *) thisEntry encoding:NSUTF8StringEncoding];
                [newEntries addObject:entryToAdd];
            }
            // We consume the bytes regardless of whether we get an entry.
            offset += (NSUInteger) bytesConsumed;
        }
        if (thisEntry != NULL) {
            CFRelease(thisEntry);
        }

        if (bytesConsumed == 0) {//该条记录并为传完 跳出循环
            // We haven't yet got enough data to parse an entry.  Wait for more data
            // to arrive.
            break;
        } else if (bytesConsumed < 0) {//出错
            // We totally failed to parse the listing.  Fail.
            [self stopReceiveWithStatus:@"Listing parse failed"];
            break;
        }
    } while (YES);

    if ([newEntries count] != 0) {
        [self addListEntries:newEntries]; //将dic添加到本类中dic的属性中
    }
    if (offset != 0) {
        [self.listData replaceBytesInRange:NSMakeRange(0, offset) withBytes:NULL length:0];//将解析完成的data移除。
    }
}

好了 差不多就这些东西了  想研究的,可以从官网下载下来这个demo,自己查看。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值