WiFi传书

作者: 浮海_2015 | 来源:发表于2018-03-14 22:59 被阅读28次

    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<HTTPResponse> *)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:@"<a href=\"%@\"> %@ </a><br/>",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];//文件存储
    }
    
    

    相关文章

      网友评论

      • IT锟:看完后受益匪浅,希望能提供下源码,这样我们就能更容易掌握了,谢谢!

      本文标题:WiFi传书

      本文链接:https://www.haomeiwen.com/subject/auzqqftx.html