WiFi传书
1、iPhone传输文件的几种方式
- 通过itunes传输文件到documents
- 通过苹果iOS11文件APP->更多->打开
- 客户端自定义协议下载(百度阅读先将文件上传到服务器,再下载)
- 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];//文件存储
}