iOS 上傳圖片至ftp服務器與通過http 上傳服務器

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

? ? ?先說一下基本簡介,在iOS端的ftp上傳使用的是CFNetWork框架,它處于核心服務框架中,提供了一個抽象化的網(wǎng)絡協(xié)議庫。使用CFNetWork框架中的CFFTPStream類提供的API能夠做很多ftp操作,例如上傳文件、下載文件、下載目錄列表,創(chuàng)建遠程目錄等等。


? ? 接下來廢話不多說 直接上代碼

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

2.接下來定義一個枚舉

enum {

kSendBufferSize = 32768

};

3.@interface里定義屬性

{

uint8_t _buffer[kSendBufferSize];

}

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

@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的事件發(fā)生都會調用代理方法

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

//寫入數(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)絡寫入錯誤"];

} 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為實際寫入的數(shù)據(jù)量,雖然緩沖區(qū)大小是固定的值,但每次寫入并不一定是充滿緩沖區(qū),可以看到NSLog的輸出值。(上傳圖片大小為428492字節(jié),約430k)。

首先是NSStreamEventOpenCompleted打開事件完成的回調,然后不斷發(fā)送NSStreamEventHasSpaceAvailable消息完成整個上傳過程。

可以看到在傳輸?shù)臅r候,bufferOffset并不是每次都是32768,所以self.bufferOffset!= self.bufferLimit是一個續(xù)傳上次未完數(shù)據(jù)的過程,而當self.bufferOffset = self.bufferLimit時,即上次的32768已經(jīng)傳完了,此時將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];

//參數(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"];

//聲明結束符:--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"]);

}

}

}];

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容