美文网首页ios初级篇iOS
iOS 上传图片至ftp服务器与通过http 上传服务器

iOS 上传图片至ftp服务器与通过http 上传服务器

作者: 狗儿蛋儿 | 来源:发表于2017-03-13 15:32 被阅读669次

        由于公司最近项目中 有个需求是要把你扫描获得的图片上传到ftp服务器 ,建于以前做的基本都是通过http 上传至服务器加上以前没有做过上传至ftp服务器,所以在此总结一下网上百度到的基本处理方法。

         先说一下基本简介,在iOS端的ftp上传使用的是CFNetWork框架,它处于核心服务框架中,提供了一个抽象化的网络协议库。使用CFNetWork框架中的CFFTPStream类提供的API能够做很多ftp操作,例如上传文件、下载文件、下载目录列表,创建远程目录等等。


        接下来废话不多说 直接上代码

    1.首先项目中倒入CFNetwork.framework 框架  并且遵循<NSStreamDelegate> 

    2.接下来定义一个枚举

    enum {

    kSendBufferSize = 32768

    };

    3.@interface里定义属性

    {

    uint8_t _buffer[kSendBufferSize];

    }

    //创建内部变量

    @property (nonatomic, retain)  NSOutputStream *  networkStream;

    @property (nonatomic, retain)  NSInputStream *  fileStream;

    @property (nonatomic, readonly) uint8_t *        buffer;

    @property (nonatomic, assign)  size_t            bufferOffset;

    @property (nonatomic, assign)  size_t            bufferLimit;

    4.@implementation里

    - (uint8_t *)buffer

    {

    return self->_buffer;

    }

    //写个方法用于上传照片

    - (void)uploadFacePicturesImage{

    NSURL *url;//ftp服务器地址

     NSString *filePath;//图片地址

    NSString *account;//账号

    NSString *password;//密码

    CFWriteStreamRef ftpStream;

    //获得输入

    NSString *urlStr = [NSString stringWithFormat:@"你要上传的ftp服务器地址“];

    url = [NSURL URLWithString:urlStr];

    filePath = [[NSBundle mainBundle] pathForResource:@"h" ofType:@"png"];//注:这里的filepath 是从bunndle中取得。我在项目里是把之前扫描获取到的图片保存在了沙盒中 从沙盒中读取的路径 同时也可以写从本地相册中获取。就不一一列举了  看你实际的需求

    account = @"你要上传的ftp服务器用户名";

    password = @"你要上传的ftp服务器密码";

    //添加后缀(文件名称)

    url = [NSMakeCollectable(CFURLCreateCopyAppendingPathComponent(NULL, (CFURLRef) url, (CFStringRef) [filePath lastPathComponent], false)) autorelease];

    //读取文件,转化为输入流

    self.fileStream = [NSInputStream inputStreamWithFileAtPath:filePath];

    [self.fileStream open];

    //为url开启CFFTPStream输出流

    ftpStream = CFWriteStreamCreateWithFTPURL(NULL, (CFURLRef) url);

    self.networkStream = (NSOutputStream *) ftpStream;

    //设置ftp账号密码

    [self.networkStream setProperty:account forKey:(id)kCFStreamPropertyFTPUserName];

    [self.networkStream setProperty:password forKey:(id)kCFStreamPropertyFTPPassword];

    //设置networkStream流的代理,任何关于networkStream的事件发生都会调用代理方法

    self.networkStream.delegate = self;

    //设置runloop

    [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [self.networkStream open];

    //完成释放链接

    CFRelease(ftpStream);

    }

    5. 设置回调方法

    #pragma mark 回调方法

    - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode

    {

    //aStream 即为设置为代理的networkStream

    switch (eventCode) {

    case NSStreamEventOpenCompleted: {

    NSLog(@"NSStreamEventOpenCompleted");

    } break;

    case NSStreamEventHasBytesAvailable: {

    NSLog(@"NSStreamEventHasBytesAvailable");

    assert(NO);    // 在上传的时候不会调用

    } break;

    case NSStreamEventHasSpaceAvailable: {

    NSLog(@"NSStreamEventHasSpaceAvailable");

    NSLog(@"bufferOffset is %zd",self.bufferOffset);

    NSLog(@"bufferLimit is %zu",self.bufferLimit);

    if (self.bufferOffset == self.bufferLimit) {

    NSInteger  bytesRead;

    bytesRead = [self.fileStream read:self.buffer maxLength:kSendBufferSize];

    if (bytesRead == -1) {

    //读取文件错误

    [self _stopSendWithStatus:@"读取文件错误"];

    } else if (bytesRead == 0) {

    //文件读取完成 上传完成

    [self _stopSendWithStatus:nil];

    } else {

    self.bufferOffset = 0;

    self.bufferLimit  = bytesRead;

    }

    }

    if (self.bufferOffset != self.bufferLimit) {

    //写入数据

    NSInteger bytesWritten;//bytesWritten为成功写入的数据

    bytesWritten = [self.networkStream write:&self.buffer[self.bufferOffset] maxLength:self.bufferLimit - self.bufferOffset];

    assert(bytesWritten != 0);

    if (bytesWritten == -1) {

    [self _stopSendWithStatus:@"网络写入错误"];

    } else {

    self.bufferOffset += bytesWritten;

    }

    }

    } break;

    case NSStreamEventErrorOccurred: {

    [self _stopSendWithStatus:@"Stream打开错误"];

    assert(NO);

    } break;

    case NSStreamEventEndEncountered: {

    // 忽略

    } break;

    default: {

    assert(NO);

    } break;

    }

    }

    //结果处理

    - (void)_stopSendWithStatus:(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;

    }

    [self _sendDidStopWithStatus:statusString];

    }

    - (void)_sendDidStopWithStatus:(NSString *)statusString

    {

    if (statusString == nil) {

    statusString = @"上传成功";

    }

    }

    按着以上操作的话就可以完成ftp上传图片了 上述回调方法说明:bytesWritten为实际写入的数据量,虽然缓冲区大小是固定的值,但每次写入并不一定是充满缓冲区,可以看到NSLog的输出值。(上传图片大小为428492字节,约430k)。

    首先是NSStreamEventOpenCompleted打开事件完成的回调,然后不断发送NSStreamEventHasSpaceAvailable消息完成整个上传过程。

    可以看到在传输的时候,bufferOffset并不是每次都是32768,所以self.bufferOffset!= self.bufferLimit是一个续传上次未完数据的过程,而当self.bufferOffset = self.bufferLimit时,即上次的32768已经传完了,此时将bufferOffset重新设置为0。

    另外 如果需要在ftp上做一些其他处理 可以github上 搜索GoldRaccoon作为参考 附上地址https://github.com/albertodebortoli/GoldRaccoon

    附上上述步骤的一些图片 以便更加详细观看



    接下来 写一下原先用NSURLConnection 上传图片

    -(void)uploadPicturesImage:(UIImage* )image nsNo:(NSString* )nsNo{

    NSData* data = UIImageJPEGRepresentation(image, 0.01);

    NSString *TWITTERFON_FORM_BOUNDARY = @"AaB03x";

    //分界线 --AaB03x

    NSString *MPboundary=[[NSString alloc]initWithFormat:@"--%@",TWITTERFON_FORM_BOUNDARY];

    //结束符 AaB03x--

    NSString *endMPboundary=[[NSString alloc]initWithFormat:@"%@--",MPboundary];

    NSMutableString *body=[[NSMutableString alloc]init];

    //参数的集合的所有key的集合

    [body appendFormat:@"%@\r\n",MPboundary];

    //声明pic字段,文件名为boris.png

    [body appendFormat:@"Content-Disposition:form-data;name=%@;filename=%@.jpg\r\n",@"名字",@"名字"];

    //声明上传文件的格式

    [body appendFormat:@"Content-Type:application/octet-stream\r\n\r\n"];

    //声明结束符:--AaB03x-

    NSString *end=[[NSString alloc]initWithFormat:@"\r\n%@",endMPboundary];

    //声明myRequestData,用来放入http body

    NSMutableData *myRequestData=[NSMutableData data];

    //将body字符串转化为UTF8格式的二进制

    [myRequestData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];

    //将image的data加入

    [myRequestData appendData:data];

    //加入结束符--AaB03x--

    [myRequestData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]];

    NSString* urlIp = [PublicFunction getHttpUrlIp];

    NSString *phone = [[NSUserDefaults standardUserDefaults] objectForKey:USER_NAME];

    NSString *urlString = [NSString stringWithFormat:@"上传url“];

    urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    NSLog(@"上传图片:%@",urlString);

    NSURL *url = [[NSURL alloc] initWithString:urlString];

    assert(url != nil);

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];

    [request setTimeoutInterval:50];

    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data;boundary=%@",TWITTERFON_FORM_BOUNDARY];

    [request addValue:contentType forHTTPHeaderField:@"Content-Type"];

    [request setHTTPMethod:@"POST"];

    [request setHTTPBody:myRequestData];

    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

    if (connectionError == nil) {

    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];

    NSLog(@"%@",dic);

    NSString *code = [dic objectForKey:@"code"];

    if ([code isEqualToString:@"00"]) {

    NSLog(@"上传成功-----msg--%@",[dic objectForKey:@"content"]);

    }else {

    NSLog(@"上传失败-----msg--%@",[dic objectForKey:@"content"]);

    }

    }

    }];

    }

    相关文章

      网友评论

      本文标题:iOS 上传图片至ftp服务器与通过http 上传服务器

      本文链接:https://www.haomeiwen.com/subject/kejnvttx.html