WiFi传书

WiFi传书

1、iPhone传输文件的几种方式

  1. 通过itunes传输文件到documents
  2. 通过苹果iOS11文件APP->更多->打开
  3. 客户端自定义协议下载(百度阅读先将文件上传到服务器,再下载)
  4. WiFi传书

2、WiFi传书的原理

  • 将手机作为服务器,在同一网络下,可以用过浏览器访问到服务器,上传文件后,服务器(即手机)将文件存储到沙盒内

3、技术选型

  • CocoaHTTPServer 是面向Mac OS X和iOS app的轻量级、可嵌入的HTTP服务器框架。
  • CocoaHTTPServer是由deusty designs开源的一个项目,支持异步socket,ipv4和ipv6,http Authentication和TLS加密
  • 浏览器上传本地书籍,使用ajax + html上传文件,表单上传的方式

4、HTTPSERVER 技术要点

1、初始化HTTPServer,设置web路径,需要提供web文件

- (void)setServer {
    self.httpServer = [[HTTPServer alloc] init];//初始化
    [self.httpServer setType:@"_http._tcp."];//通过Bonjour服务发布的类型,允许浏览器访问
    [self.httpServer setPort:8080];//设置端口
    [self.httpServer setConnectionClass:[MyHTTPConnection class]];//设置处理连接的自定义类文件
    NSString *webPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Web"];
    DDLogInfo(@"Setting document root: %@", webPath);
    [self.httpServer setDocumentRoot:webPath];//设置服务器根目录
    NSLog(@"home = %@",NSHomeDirectory());
}

2、 设置支持的方法

- (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)path
{
    HTTPLogTrace();
    
    // Add support for POST
    if ([method isEqualToString:@"POST"])
    {
        return YES;
    }
    if ([method isEqualToString:@"DELETE"]) {
        return YES;
    }
    if ([method isEqualToString:@"GET"]) {
        return YES;
    }
    return [super supportsMethod:method atPath:path];
}

2、 处理请求

- (NSObject *)httpResponseForMethod:(NSString *)method URI:(NSString *)path
{
    HTTPLogTrace();
    
    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:@" %@ 
",filePath, [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]; }

3、 处理文件上传内容

上次有2个part:一个是文件名,另一个是文件内容

- (BOOL)expectsRequestBodyFromMethod:(NSString *)method atPath:(NSString *)path
{
    HTTPLogTrace();
    
    // Inform HTTP server that we expect a body to accompany a POST request
    
    if([method isEqualToString:@"POST"] && [path hasPrefix:@"/upload"]) {
        // 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];
}

4、 处理body数据

- (void)processBodyData:(NSData *)postDataChunk
{
    HTTPLogTrace();
    // append data to the parser. It will invoke callbacks to let us handle
    // parsed data.
    [request appendData:postDataChunk];//post body存储
    [parser appendData:postDataChunk];//文件存储
}

你可能感兴趣的:(WiFi传书)