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

    由于公司最近项目中 有个需求是要把你扫描获得的图片上传到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"]);

}

}

}];

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,653评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,321评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,833评论 0 324
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,472评论 1 266
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,306评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,274评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,658评论 3 385
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,335评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,638评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,697评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,454评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,311评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,699评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,986评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,254评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,647评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,847评论 2 335

推荐阅读更多精彩内容