http 是计算机之间通讯协议的比较简单的一种。在iPhone上,由于没有同步数据和文件共享,所以实现PC与设备之间的数据传输的最佳方式就是在程序中嵌套一个http 服务器。在这篇帖子中,我将简单的演示第三方的http 服务器的使用。

示例程序运行如下(在PC端输入设备的IP和端口,便可选取当前PC的文件进行上传至当前的设备)

该服务器涉及的相关类如下图所示

代码实现,创建一个自己需求的HttpConnection类继承于第三方的HttpConnection,代码如下

MyHTTPConnection.h

#import "HTTPConnection.h"

@class MultipartFormDataParser;

@interface MyHTTPConnection : HTTPConnection

{

MultipartFormDataParser * parser;

NSFileHandle * storeFile;

NSMutableArray * uploadedFiles;

}

@end

MyHTTPConnection.m

#import "MyHTTPConnection.h"

#import "HTTPMessage.h"

#import "HTTPDataResponse.h"

#import "DDNumber.h"

#import "HTTPLogging.h"

#import "MultipartFormDataParser.h"

#import "MultipartMessageHeaderField.h"

#import "HTTPDynamicFileResponse.h"

#import "HTTPFileResponse.h"

static const int httpLogLevel = HTTP_LOG_LEVEL_VERBOSE;

@interface MyHTTPConnection ()

{

float totalSize;

float progress;

}

@end

@implementation MyHTTPConnection

个人需要,1-8的方法都有实现

1:- (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)path

{

NSLog(@"%s",__FUNCTION__);

HTTPLogTrace();

if (  [ method isEqualToString:@"POST"] ) {

if ( [path isEqualToString:@"/upload.html"] ) {

return YES;

}

}

return  [super supportsMethod:method atPath:path];

}

2:-(BOOL)expectsRequestBodyFromMethod:(NSString *)method atPath:(NSString *)path{

if([method isEqualToString:@"POST"] && [path isEqualToString:@"/upload.html"]) {

// here we need to make sure, boundary is set in header

NSString* contentType = [request headerField:@"Content-Type"];

NSUInteger paramsSeparator = [contentType rangeOfString:@";"].location;

if( NSNotFound == paramsSeparator ) {

return NO;

}

if( paramsSeparator >= contentType.length - 1 ) {

return NO;

}

NSString* type = [contentType substringToIndex:paramsSeparator];

if( ![type isEqualToString:@"multipart/form-data"] ) {

// we expect multipart/form-data content type

return NO;

}

// enumerate all params in content-type, and find boundary there

NSArray* params = [[contentType substringFromIndex:paramsSeparator + 1] componentsSeparatedByString:@";"];

for( NSString* param in params ) {

paramsSeparator = [param rangeOfString:@"="].location;

if( (NSNotFound == paramsSeparator) || paramsSeparator >= param.length - 1 ) {

continue;

}

NSString* paramName = [param substringWithRange:NSMakeRange(1, paramsSeparator-1)];

NSString* paramValue = [param substringFromIndex:paramsSeparator+1];

if( [paramName isEqualToString: @"boundary"] ) {

// let's separate the boundary from content-type, to make it more handy to handle

[request setHeaderField:@"boundary" value:paramValue];

}

}

// check if boundary specified

if( nil == [request headerField:@"boundary"] )  {

return NO;

}

return YES;

}

return [super expectsRequestBodyFromMethod:method atPath:path];

}

3:- (NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path{

if ([method isEqualToString:@"POST"] && [path isEqualToString:@"/upload.html"])

{

// this method will generate response with links to uploaded file

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

for( NSString* filePath in uploadedFiles ) {

//generate links

[filesStr appendFormat:@"%@<br/><br/>", [filePath lastPathComponent]];

}

NSString* templatePath = [[config documentRoot] stringByAppendingPathComponent:@"upload.html"];

NSDictionary* replacementDict = [NSDictionary dictionaryWithObject:filesStr forKey:@"MyFiles"];

// use dynamic file response to apply our links to response template

return [[HTTPDynamicFileResponse alloc] initWithFilePath:templatePath forConnection:self separator:@"%" replacementDictionary:replacementDict];

}

if( [method isEqualToString:@"GET"] && [path hasPrefix:@"/upload/"] ) {

// let download the uploaded files

return [[HTTPFileResponse alloc] initWithFilePath: [[config documentRoot] stringByAppendingString:path] forConnection:self];

}

return [super httpResponseForMethod:method URI:path];

}

4:- (void)prepareForBodyWithSize:(UInt64)contentLength{

HTTPLogTrace();

totalSize = contentLength/1000.0/1000.0;

NSLog(@"%f",contentLength/1000.0/1000.0);

// set up mime parser

NSString* boundary = [request headerField:@"boundary"];

parser = [[MultipartFormDataParser alloc] initWithBoundary:boundary formEncoding:NSUTF8StringEncoding];

parser.delegate = self;

uploadedFiles = [[NSMutableArray alloc] init];

}

5:- (void)processBodyData:(NSData *)postDataChunk{

HTTPLogTrace();

progress += postDataChunk.length/1024.0/1024.0;

NSLog(@"%f",progress);

NSString * temp  = [ NSString stringWithFormat:@"上传进度:%.2fMB/%.2fMB",progress,totalSize ];

dispatch_async(dispatch_get_main_queue(), ^{

[SVProgressHUD showProgress:progress/totalSize status:temp maskType:SVProgressHUDMaskTypeBlack];

});

// append data to the parser. It will invoke callbacks to let us handle

// parsed data.

[parser appendData:postDataChunk];

}

6:- (void) processStartOfPartWithHeader:(MultipartMessageHeader*) header{

NSLog(@"%s",__FUNCTION__);

MultipartMessageHeaderField* disposition = [header.fields objectForKey:@"Content-Disposition"];

NSString* filename = [[disposition.params objectForKey:@"filename"] lastPathComponent];

NSLog(@"####filename=%@",filename);

if ( (nil == filename) || [filename isEqualToString: @""] ) {

// it's either not a file part, or

// an empty form sent. we won't handle it.

return;

}

NSString* uploadDirPath = [self CreatreTempDir] ;

// NSLog(@"uploadDirPath%@",[self CreatDir]);

BOOL isDir = YES;

if (![[NSFileManager defaultManager]fileExistsAtPath:uploadDirPath isDirectory:&isDir ]) {

[[NSFileManager defaultManager]createDirectoryAtPath:uploadDirPath withIntermediateDirectories:YES attributes:nil error:nil];

}

NSString * filePath = [uploadDirPath stringByAppendingPathComponent:filename];

NSFileManager * fileManager = [NSFileManager defaultManager];

if( [[NSFileManager defaultManager] fileExistsAtPath:filePath] ) {

storeFile = nil;

}

else {

HTTPLogVerbose(@"Saving file to %@", filePath);

NSError *error;

if(![[NSFileManager defaultManager] createDirectoryAtPath:uploadDirPath withIntermediateDirectories:true attributes:nil error:&error]) {

HTTPLogError(@"Could not create directory at path: %@----%@", filePath,error);

}

if(![[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]) {

HTTPLogError(@"Could not create file at path: %@", filePath);

}

storeFile = [NSFileHandle fileHandleForWritingAtPath:filePath];

[uploadedFiles addObject: [NSString stringWithFormat:@"/upload/%@", filename]];

}

}

7:- (void) processContent:(NSData*) data WithHeader:(MultipartMessageHeader*) header{

if(!storeFile)

{

MultipartMessageHeaderField* disposition = [header.fields objectForKey:@"Content-Disposition"];

NSString* filename = [[disposition.params objectForKey:@"filename"] lastPathComponent];

NSLog(@"####filename=%@",filename);

if ( (nil == filename) || [filename isEqualToString: @""] ) {

// it's either not a file part, or

// an empty form sent. we won't handle it.

return;

}

NSString* uploadDirPath = [self CreatreTempDir] ;

NSString * filePath = [uploadDirPath stringByAppendingPathComponent:filename];

storeFile = [NSFileHandle fileHandleForWritingAtPath:filePath];

[uploadedFiles addObject: [NSString stringWithFormat:@"/upload/%@", filename]];

}

if( storeFile ) {

[storeFile writeData:data];

}

}

8:- (void) processEndOfPartWithHeader:(MultipartMessageHeader*) header{

dispatch_async(dispatch_get_main_queue(), ^{

[SVProgressHUD dismiss];

});

progress = 0.f;

MultipartMessageHeaderField* disposition = [header.fields objectForKey:@"Content-Disposition"];

NSString* filename = [[disposition.params objectForKey:@"filename"] lastPathComponent] ;

// NSLog(@"####END ---filename=%@",filename);

NSString * tempFilePath = [[ self CreatreTempDir ] stringByAppendingPathComponent:filename];

NSMutableArray *arraynumber = [NSMutableArray arrayWithContentsOfFile:[Global getChangePathName]];

NSString *strnumber = [arraynumber lastObject];

NSString * uploadFilePath = [[ self CreatDir ] stringByAppendingPathComponent: [[NSString stringWithFormat:@"%d.",[strnumber intValue] + 1 ] stringByAppendingString:filename]];

[arraynumber addObject:[NSString stringWithFormat:@"%d", [strnumber intValue] + 1]];

[arraynumber writeToFile:[Global getChangePathName] atomically:YES];

BOOL result = [ self copyMissFile:tempFilePath toPath:uploadFilePath ];

if (result) {

NSLog(@"移动成功");

}else{

NSLog(@"移动失败");

}

[storeFile closeFile];

storeFile = nil;

}

- (BOOL)copyMissFile:(NSString * )sourcePath toPath:(NSString *)toPath{

BOOL retVal ;

NSLog(@"%s",__FUNCTION__);

//    if ( [fileManger fileExistsAtPath:toPath]  ) {

//        [fileManger removeItemAtPath:toPath error:nil];

//    }

retVal = [[ NSFileManager defaultManager ] moveItemAtPath:sourcePath toPath:toPath error:nil];

return retVal;

}

下面两个方法都是创建文件,大家自己可以随意定义

-(NSString *)CreatDir;

-(NSString *)CreatreTempDir;

下面根据需求实现以下这些方法,我是在全局的类里面实现的

Global.m

+ (BOOL)createiPhoneServer  //创建并设置iPhone的服务器

{

Global * global = [ Global sharedGlobal ];

global.httpServer = [[HTTPServer alloc] init];

[global.httpServer setType:@"_http._tcp."];

NSString *docRoot = [[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"MyResources"] stringByAppendingPathComponent:@"Web"];

BOOL  isDir  = YES ;

if ( [[NSFileManager defaultManager] fileExistsAtPath:docRoot isDirectory:&isDir  ]  ) {

NSLog(@"找到Web文件夹");

}

[global.httpServer setDocumentRoot:docRoot];

[global.httpServer setPort:Http_Port];//本地端口

[global.httpServer setConnectionClass:[MyHTTPConnection class]];//设置连接类为我们之前代码实现的连接类

return YES;

}

//开启服务器

+ (BOOL)startServer

{

Global * global = [ Global sharedGlobal];

NSError * error;

if ( [global.httpServer start:&error] ) {

NSLog(@"开启成功%u",[global.httpServer listeningPort]);

return YES;

}else

{

NSLog(@"开启失败,%@",error);

return NO;

}

}

+ (BOOL)stopServer

{

[[Global sharedGlobal].httpServer stop:YES];

return YES;

}

//获得当前设备的IP

+(NSString *)getIPAddress

{

NSString *address = @"开启失败";

struct ifaddrs *interfaces = NULL;

struct ifaddrs *temp_addr = NULL;

int success = 0;

// retrieve the current interfaces - returns 0 on success

success = getifaddrs(&interfaces);

if (success == 0) {

// Loop through linked list of interfaces

temp_addr = interfaces;

while(temp_addr != NULL) {

if(temp_addr->ifa_addr->sa_family == AF_INET) {

// Check if interface is en0 which is the wifi connection on the iPhone

if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {

// Get NSString from C String

address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];

}

}

temp_addr = temp_addr->ifa_next;

}

}

// Free memory

freeifaddrs(interfaces);

NSString * str = nil;

if ( [address isEqualToString:@"开启失败"] ) {

str = @"开启失败";

}else {

str = [NSString stringWithFormat:@"http://%@:%d",address, Http_Port ];

}

return str;

}

//获取当前设备的网络状态

+(NSString *) getDeviceSSID

{

NSArray *ifs = (__bridge id)CNCopySupportedInterfaces() ;

id info = nil;

for (NSString *ifnam in ifs) {

info = (__bridge id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);

if (info && [info count]) {

break;

}

}

NSDictionary *dctySSID = (NSDictionary *)info;

NSString *ssid = [ dctySSID objectForKey:@"SSID" ];

ssid = ssid== nil?@"无网络":ssid;

return ssid;

}

然后再你需要的地方开启这个服务即可,至此http 服务搭建完成,开启服务之后就可在PC的浏览器输入当前的设备IP地址和端口,如http://192.168.2.155:8088,然后上传所需的文件即可,根据程序设计,这些文件会存在相应的地方

iOS 实现简单的Http 服务的更多相关文章

  1. iOS开发 简单实现视频音频的边下边播 (转)

      1.ios视频音频边缓存边播放,缓存时可以在已下载的部分拖拽进度条. 3.无论是下载到一半退出还是下载完退出,已缓存的数据都存到自己指定的一个路径.如果已下载完,下次播放时可以不再走网络,直接播放 ...

  2. 通过HttpListener实现简单的Http服务

    使用HttpListener实现简单的Http服务 HttpListener提供一个简单的.可通过编程方式控制的 HTTP 协议侦听器.使用它可以很容易的提供一些Http服务,而无需启动IIS这类大型 ...

  3. iOS上简单推送通知(Push Notification)的实现

    iOS上简单推送通知(Push Notification)的实现 根据这篇很好的教程(http://www.raywenderlich.com/3443/apple-push-notification ...

  4. 树莓派(Raspberry Pi)搭建简单的lamp服务

    树莓派(Raspberry Pi)搭建简单的lamp服务: 1. LAMP 的安装 sudo apt-get install apache2 mysql-server mysql-client php ...

  5. 构建简单的 C++ 服务组件,第 1 部分: 服务组件体系结构 C++ API 简介

    构建简单的 C++ 服务组件,第 1 部分: 服务组件体系结构 C++ API 简介 熟悉将用于 Apache Tuscany SCA for C++ 的 API.您将通过本文了解该 API 的主要组 ...

  6. Netty4.0学习笔记系列之三:构建简单的http服务(转)

    http://blog.csdn.net/u013252773/article/details/21254257 本文主要介绍如何通过Netty构建一个简单的http服务. 想要实现的目的是: 1.C ...

  7. 简单ESB的服务架构

    简单ESB的服务架构 这几个月一直在修改架构,所以迟迟没有更新博客. 新的架构是一个基于简单esb的服务架构,主要构成是esb服务注册,wcf服务,MVC项目构成. 首先,我门来看一看解决方案, 1. ...

  8. 新项目架构从零开始(三)------基于简单ESB的服务架构

    这几个月一直在修改架构,所以迟迟没有更新博客. 新的架构是一个基于简单esb的服务架构,主要构成是esb服务注册,wcf服务,MVC项目构成. 首先,我门来看一看解决方案, 1.Common 在Com ...

  9. 简单 TCP/IP 服务功能

    本主题使用每台 Windows 计算机上提供的 Echo 和 Quote of the Day 服务.在所有 Windows 版本中都提供了简单 TCP/IP 服务功能.该功能会提供了以下服务:Cha ...

随机推荐

  1. python常用代码

    #coding=utf-8 import urllib import re def getHtml(url): page = urllib.urlopen(url) html = page.read( ...

  2. 第二周 WBS、NABCD查阅

    WBS WBS:工作分解结构(Work Breakdown Structure) 创建WBS:创建WBS是把项目可交付成果和项目工作分解成较小的,更易于管理的组成部分的过程. WBS是项目管理重要的专 ...

  3. BluetoothAdapter.LeScanCallback 参考文档

      BluetoothAdapter.LeScanCallback 参考文档   [翻译自: android开发文档] Class Overview:回调接口被用于传输LE扫描后的结果; 详情参看: ...

  4. hdu----(1257)最少拦截系统(dp/LIS)

    最少拦截系统 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  5. linux安装.run

    chmod +x ./framework-3.6.0-linux-full.runsudo ./framework-3.6.0-linux-full.run

  6. linux如何修改主机名

    一:#hostname hn1 二:修改/etc/sysconfig/network中的 HOSTNAME=hn1三:修改/etc/hosts文件  127.0.0.1 hn1

  7. MongoDB 一对多关系建模

    转文: 本篇博客翻译自: http://blog.mongodb.org/post/87200945828/6-rules-of-thumb-for-mongodb-schema-design-par ...

  8. 使用DD_belatedPNG让IE6支持PNG透明图片

    使用DD_belatedPNG让IE6支持PNG透明图片 众所周知IE6不支持透明的PNG图片,而PNG图片在Web设计方面表现力上,具有其它图形格式所达不到的效果,IE6这一致命缺陷极大地限制了We ...

  9. 引用CSS文件到html网页里方法

        引用CSS文件到Html方法-css引入,css引用 使用不同的方法来引用css样式表,最终到达的效果相同,但是使用不同方法应用的css文件将影响到SEO及网页打开速度效率. html引用cs ...

  10. vim命令/压缩和解压命令

    gzip命令 -d 解压 -#  1 为最快 但容量问题 . 9为最好 .6为默认 gzip install.log 比较好理解,windows里面类似的,记住zip 和unzip是可以目录或者文件解 ...