iOS 上傳圖片至ftp服務(wù)器與通過(guò)http 上傳服務(wù)器

? ? 由于公司最近項(xiàng)目中 有個(gè)需求是要把你掃描獲得的圖片上傳到ftp服務(wù)器 ,建于以前做的基本都是通過(guò)http 上傳至服務(wù)器加上以前沒有做過(guò)上傳至ftp服務(wù)器并级,所以在此總結(jié)一下網(wǎng)上百度到的基本處理方法拂檩。

? ? ?先說(shuō)一下基本簡(jiǎn)介,在iOS端的ftp上傳使用的是CFNetWork框架嘲碧,它處于核心服務(wù)框架中,提供了一個(gè)抽象化的網(wǎng)絡(luò)協(xié)議庫(kù)稻励。使用CFNetWork框架中的CFFTPStream類提供的API能夠做很多ftp操作,例如上傳文件愈涩、下載文件望抽、下載目錄列表,創(chuàng)建遠(yuǎn)程目錄等等履婉。


? ? 接下來(lái)廢話不多說(shuō) 直接上代碼

1.首先項(xiàng)目中倒入CFNetwork.framework 框架 ?并且遵循<NSStreamDelegate>?

2.接下來(lái)定義一個(gè)枚舉

enum {

kSendBufferSize = 32768

};

3.@interface里定義屬性

{

uint8_t _buffer[kSendBufferSize];

}

//創(chuàng)建內(nèi)部變量

@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;

}

//寫個(gè)方法用于上傳照片

- (void)uploadFacePicturesImage{

NSURL *url;//ftp服務(wù)器地址

?NSString *filePath;//圖片地址

NSString *account;//賬號(hào)

NSString *password;//密碼

CFWriteStreamRef ftpStream;

//獲得輸入

NSString *urlStr = [NSString stringWithFormat:@"你要上傳的ftp服務(wù)器地址“];

url = [NSURL URLWithString:urlStr];

filePath = [[NSBundle mainBundle] pathForResource:@"h" ofType:@"png"];//注:這里的filepath 是從bunndle中取得煤篙。我在項(xiàng)目里是把之前掃描獲取到的圖片保存在了沙盒中 從沙盒中讀取的路徑 同時(shí)也可以寫從本地相冊(cè)中獲取。就不一一列舉了 ?看你實(shí)際的需求

account = @"你要上傳的ftp服務(wù)器用戶名";

password = @"你要上傳的ftp服務(wù)器密碼";

//添加后綴(文件名稱)

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

//讀取文件毁腿,轉(zhuǎn)化為輸入流

self.fileStream = [NSInputStream inputStreamWithFileAtPath:filePath];

[self.fileStream open];

//為url開啟CFFTPStream輸出流

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

self.networkStream = (NSOutputStream *) ftpStream;

//設(shè)置ftp賬號(hào)密碼

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

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

//設(shè)置networkStream流的代理辑奈,任何關(guān)于networkStream的事件發(fā)生都會(huì)調(diào)用代理方法

self.networkStream.delegate = self;

//設(shè)置runloop

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

[self.networkStream open];

//完成釋放鏈接

CFRelease(ftpStream);

}


5. 設(shè)置回調(diào)方法

#pragma mark 回調(diào)方法

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

{

//aStream 即為設(shè)置為代理的networkStream

switch (eventCode) {

case NSStreamEventOpenCompleted: {

NSLog(@"NSStreamEventOpenCompleted");

} break;

case NSStreamEventHasBytesAvailable: {

NSLog(@"NSStreamEventHasBytesAvailable");

assert(NO);? ? // 在上傳的時(shí)候不會(huì)調(diào)用

} 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) {

//讀取文件錯(cuò)誤

[self _stopSendWithStatus:@"讀取文件錯(cuò)誤"];

} else if (bytesRead == 0) {

//文件讀取完成 上傳完成

[self _stopSendWithStatus:nil];

} else {

self.bufferOffset = 0;

self.bufferLimit? = bytesRead;

}

}

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

//寫入數(shù)據(jù)

NSInteger bytesWritten;//bytesWritten為成功寫入的數(shù)據(jù)

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

assert(bytesWritten != 0);

if (bytesWritten == -1) {

[self _stopSendWithStatus:@"網(wǎng)絡(luò)寫入錯(cuò)誤"];

} else {

self.bufferOffset += bytesWritten;

}

}

} break;

case NSStreamEventErrorOccurred: {

[self _stopSendWithStatus:@"Stream打開錯(cuò)誤"];

assert(NO);

} break;

case NSStreamEventEndEncountered: {

// 忽略

} break;

default: {

assert(NO);

} break;

}

}

//結(jié)果處理

- (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上傳圖片了 上述回調(diào)方法說(shuō)明:bytesWritten為實(shí)際寫入的數(shù)據(jù)量,雖然緩沖區(qū)大小是固定的值已烤,但每次寫入并不一定是充滿緩沖區(qū)鸠窗,可以看到NSLog的輸出值。(上傳圖片大小為428492字節(jié)胯究,約430k)稍计。

首先是NSStreamEventOpenCompleted打開事件完成的回調(diào),然后不斷發(fā)送NSStreamEventHasSpaceAvailable消息完成整個(gè)上傳過(guò)程裕循。

可以看到在傳輸?shù)臅r(shí)候臣嚣,bufferOffset并不是每次都是32768,所以self.bufferOffset!= self.bufferLimit是一個(gè)續(xù)傳上次未完數(shù)據(jù)的過(guò)程剥哑,而當(dāng)self.bufferOffset = self.bufferLimit時(shí)硅则,即上次的32768已經(jīng)傳完了,此時(shí)將bufferOffset重新設(shè)置為0星持。

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

附上上述步驟的一些圖片 以便更加詳細(xì)觀看




接下來(lái) 寫一下原先用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];

//結(jié)束符 AaB03x--

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

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

//參數(shù)的集合的所有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"];

//聲明結(jié)束符:--AaB03x-

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

//聲明myRequestData,用來(lái)放入http body

NSMutableData *myRequestData=[NSMutableData data];

//將body字符串轉(zhuǎn)化為UTF8格式的二進(jìn)制

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

//將image的data加入

[myRequestData appendData:data];

//加入結(jié)束符--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"]);

}

}

}];

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末督暂,一起剝皮案震驚了整個(gè)濱河市揪垄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌逻翁,老刑警劉巖饥努,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異八回,居然都是意外死亡酷愧,警方通過(guò)查閱死者的電腦和手機(jī)驾诈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)溶浴,“玉大人乍迄,你說(shuō)我怎么就攤上這事∈堪埽” “怎么了闯两?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)谅将。 經(jīng)常有香客問我漾狼,道長(zhǎng),這世上最難降的妖魔是什么饥臂? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任逊躁,我火速辦了婚禮,結(jié)果婚禮上隅熙,老公的妹妹穿的比我還像新娘稽煤。我一直安慰自己,他們只是感情好猛们,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布念脯。 她就那樣靜靜地躺著,像睡著了一般弯淘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吉懊,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天庐橙,我揣著相機(jī)與錄音,去河邊找鬼借嗽。 笑死态鳖,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的恶导。 我是一名探鬼主播浆竭,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼惨寿!你這毒婦竟也來(lái)了邦泄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤裂垦,失蹤者是張志新(化名)和其女友劉穎顺囊,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蕉拢,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡特碳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年诚亚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片午乓。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡站宗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出益愈,到底是詐尸還是另有隱情梢灭,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布腕唧,位于F島的核電站或辖,受9級(jí)特大地震影響枢里,放射性物質(zhì)發(fā)生泄漏训堆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一窗骑、第九天 我趴在偏房一處隱蔽的房頂上張望但惶。 院中可真熱鬧耳鸯,春花似錦、人聲如沸膀曾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)添谊。三九已至财喳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間斩狱,已是汗流浹背耳高。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留所踊,地道東北人泌枪。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像秕岛,于是被迫代替她去往敵國(guó)和親碌燕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容