美文网首页
记一次对Anyview阅读iOS版wifi传书功能的抹黑探索

记一次对Anyview阅读iOS版wifi传书功能的抹黑探索

作者: 小葫芦lu | 来源:发表于2016-03-15 22:22 被阅读1395次

记一次对Anyview阅读iOS版wifi传书功能的抹黑探索


原因

由于我最习惯使用的看小说的软件是 Anyview 阅读 ,当然也是习惯使然,从塞班时代,到安卓,到iOS,一直如此。

而我习惯于阅读本地书籍,即从网络下载之后,不用网也能看,主要是能一气呵成,看书要停顿,不太好。但是iOS有个不太友好的地方,就是不能随便操作本地文件,当然本着没有条件创造条件也要上的原则,使用wifi传输文件,就成为了一种折中的选择。

对于wifi传书的基本,在上篇博客iOS实现wifi传书功能中已经说过了。

但是在真实项目中使用,实在是毫无体验可言。我试着做过,靠着一点前端的基础,基本做了个demo,但实在拿不出手。


试错
  1. 从实现获取文件目录开始,使用jquery的ajax get请求,因为要实现删除的功能,所以返回的html中带了一个调用当前js的方法的button,(这个方法确实太傻),但是调用时却不执行,于是返回时将button改成a标签,之后就可以了

  2. 最关键的还是文件上传,在之前博客中,是可以文件上传的,但是上传之后,页面跳转,这就太丑了,对于只有几个简单功能来说的服务器来说,体验太差了。

    之后找到了一种可以实现ajax上传的方式,使用Ajaxupload.js上传文件,但是上传之后成功的回调,却无法调用本地js,替换当前页面的数据,而且不能显示进度条。劣势自然而然。

    最后让我想到一个方法,因为iOS app作为服务器,服务器文件只能放在ipa包内,所以一不做二不休,直接拆包,拿到 Anyview阅读 中的web服务器文件,然而拿到是拿到了,枉我还做过pc网站,竟然萌萌哒,看来js还是要多加学习呀。看来修改前端是行不通了,那就另寻他路。

    他路

    没那心思去滤清前端的逻辑,那就从中间作为入口,使用 Charles 监听接口,根据传过来的数据,处理之后,仿照之前的数据返回不就行了。于是,一切照章进行,除了下载功能,其他均已实现。


废话少说,当然是上代码

AnyHTTPConnection.m

  • 设置支持的方法
- (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];
}
  • 处理文件上传内容
- (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];
}
  • 处理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];//文件存储
}
  • 最关键的所在,处理请求
- (NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path
{
    HTTPLogTrace();
    
    //页面初始化时,填充数据
    if ([path isEqualToString:@"/index.html"] || [path isEqualToString:@"/"] || [path hasPrefix:@"/index.html"]) {
        NSString* templatePath = [[config documentRoot] stringByAppendingPathComponent:@"index.html"];
        NSMutableDictionary *replacementDict = [NSMutableDictionary dictionary];
        [replacementDict setObject:@"Wifi传书" forKey:@"title"];
        [replacementDict setObject:@"iOS" forKey:@"device"];
        [replacementDict setObject:@"XFReader" forKey:@"header"];
        [replacementDict setObject:@"拖拽文件到窗口或者点击“上传书籍”按钮选择您要上传的书籍,上传完成后就可以在书架上看到您上传的书啦,赶紧上传吧!" forKey:@"prologue"];
        [replacementDict setObject:@"" forKey:@"epilogue"];
        [replacementDict setObject:@"XFReader 1.0.0" forKey:@"footer"];
        return [[HTTPDynamicFileResponse alloc] initWithFilePath:templatePath forConnection:self separator:@"%" replacementDictionary:replacementDict];
    }
    
    //表单数据,返回NSString类型json数据[{"name":"1.txt","path":"/upload/1.txt","size":"12400"},{"name":"2.txt","path":"/upload/2.txt","size":"15000"}]
    if ([path hasPrefix:@"/list?path="] && [method isEqualToString:@"GET"]) {
        NSData *response = [self dictToData:[self filesInfoList]];
        return [[HTTPDataResponse alloc] initWithData:response];
    }
    
    //下载 返回 文件内容
    if ([path hasPrefix:@"/download?path="] && [method isEqualToString:@"GET"]) {
        //获取body内容
        NSArray *tArr = [[path stringByRemovingPercentEncoding] componentsSeparatedByString:@"="];
        if (tArr.count >= 2) {
            //返回文件数据
            //NSData *data = [NSData dataWithContentsOfFile:[self filePath:tArr[1]] options:(NSDataReadingUncached) error:nil];
            //return [[HTTPDataResponse alloc] initWithData:data];
        }else {
            //参数错误
            NSData *response = [@"参数错误" dataUsingEncoding:NSUTF8StringEncoding];
            return [[HTTPDataResponse alloc] initWithData:response];
        }
    }
    
    //删除 根据路径删除文件
    if ([path hasPrefix:@"/delete"] && [method isEqualToString:@"POST"]) {
        NSString *body = [[NSString alloc] initWithData:request.body encoding:NSUTF8StringEncoding];
        NSArray *tArr = [[body stringByRemovingPercentEncoding] componentsSeparatedByString:@"="];
        if (tArr.count >= 2) {
            [self deleteFile:tArr[1]];//删除文件
        }
        NSData *response = [@"{}" dataUsingEncoding:NSUTF8StringEncoding];
        return [[HTTPDataResponse alloc] initWithData:response];
    }
    
    //上传文件
    if ([path hasPrefix:@"/upload"] && [method isEqualToString:@"POST"]) {
        [self moveFiles:uploadedFiles];
        NSData *response = [@"{}" dataUsingEncoding:NSUTF8StringEncoding];
        return [[HTTPDataResponse alloc] initWithData:response];
    }
    
    //重命名 根据新旧路径 修改文件名 oldPath=/upload/1.txt&newPath=/upload/2.txt
    if ([path hasPrefix:@"/move"] && [method isEqualToString:@"POST"]) {
        //oldPath, newPath
        NSString *body = [[[NSString alloc] initWithData:request.body encoding:NSUTF8StringEncoding] stringByRemovingPercentEncoding];
        NSLog(@"body = %@",body);
        NSArray *arr = [body componentsSeparatedByString:@"&"];//oldPath=/upload/1.txt
        NSArray *tA0 = [arr[0] componentsSeparatedByString:@"="];//olodPath  /upload/1.txt
        NSArray *tA1 = [arr[1] componentsSeparatedByString:@"="];
        NSString *oldPath = @"";
        NSString *newPath = @"";
        if ([tA0[0] isEqualToString:@"oldPath"]) {
            oldPath = tA0[1];
            newPath = tA1[1];
        }else {
            oldPath = tA1[1];
            newPath = tA0[1];
        }
        [self renameFile:oldPath newPath:newPath];
        NSData *response = [@"{}" dataUsingEncoding:NSUTF8StringEncoding];
        return [[HTTPDataResponse alloc] initWithData:response];
    }
    
    return [super httpResponseForMethod:method URI:path];
}

相关文章

  • 记一次对Anyview阅读iOS版wifi传书功能的抹黑探索

    记一次对Anyview阅读iOS版wifi传书功能的抹黑探索 原因 由于我最习惯使用的看小说的软件是 Anyvie...

  • iOS实现wifi传书功能

    我经常使用「多看」和「掌阅」App 看书,其中有一个共同的功能就是 WiFi 传书,根据 App 的提示在电脑浏览...

  • iOS实现WIFI传书

    问题业务场景上存在需要将手机里的文件、图片传递给其他的设备,不仅仅局限于传书、资料啥的都有可能传递 方案最base...

  • iOS客户端 获取WIFI ssid等信息资料

    iOS Wifi编程要点总结-获取WIFI名和IP iOS客户端公共WIFI解决方案 iOS开发中WiFi相关功能...

  • iOS之WiFi IP相关

    Questions在[iOS实现WIFI传书]中有一个获取IP的步骤在此顺带总结一份关于WIFI与IP的常用内容设...

  • WiFi

    iOS开发中WiFi相关功能总结 iOS 获取系统wifi列表,wifi信号强度,并给wifi设置密码,标签(副标...

  • WiFi传书

    WiFi传书 1、iPhone传输文件的几种方式 通过itunes传输文件到documents 通过苹果iOS11...

  • iOS MultipeerConnectivity

    问题承接上文[iOS实现WIFI传书],如果去掉局域网会如何?能否实现设备间文件传输iOS设备间的数据传输常用方式...

  • iOS

    iOS调用系统功能 [1] 相册、相机 [2] WiFi、BlueTooth

  • iOS探索 多线程之GCD应用

    摘于文章:链接: 欢迎阅读iOS探索系列(按序阅读食用效果更加)iOS探索 alloc流程iOS探索 内存对齐&m...

网友评论

      本文标题:记一次对Anyview阅读iOS版wifi传书功能的抹黑探索

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