cocoahttpserver使用具体解释(二)
接下来,我们接着去学习怎样去接收处理web上传的数据
1 首先我们创建一个
@interface WTZHTTPConnection : HTTPConnection
在这个类中我们用于处理接受文件并存储到app文档
同一时候不要忘记了设置httpserver的Connectio类
[httpServer setConnectionClass:[WTZHTTPConnectionclass]];
所有的代码例如以下
.h文件
#define UPLOAD_FILE_PROGRESS @"uploadfileprogress" #import <Foundation/Foundation.h>
#import "HTTPConnection.h" @interface WTZHTTPConnection : HTTPConnection
{
int dataStartIndex;
NSMutableArray *multipartData;
BOOL postHeaderOK;
} - (BOOL) isBeginOfOctetStream; @end
.m文件
#import "WTZHTTPConnection.h"
@implementation WTZHTTPConnection
- (void)dealloc {
[multipartData release];
[super dealloc];
}
//扩展HTTPServer支持的请求类型,默认支持GET,HEAD。不支持POST
- (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)relativePath
{
if ([@"POST" isEqualToString:method])
{
return YES;
}
return [super supportsMethod:method atPath:relativePath];
}
//处量返回的response数据
- (NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path
{
return [super httpResponseForMethod:method URI:path];
}
//处理POST请求提交的数据流(以下方法是改自 Andrew Davidson的类)
- (void)processDataChunk:(NSData *)postDataChunk
{
NSLog(@"processDataChunk function called");
//multipartData初始化不放在init函数中, 当前相似乎不经init函数初始化
if (multipartData == nil) {
multipartData = [[NSMutableArray alloc] init];
}
//处理multipart/form-data的POST请求中Body数据集中的表单值域并创建文件
if (!postHeaderOK)
{
//0x0A0D: 换行符
UInt16 separatorBytes = 0x0A0D;
NSData* separatorData = [NSData dataWithBytes:&separatorBytes length:2];
int l = (int)[separatorData length];
for (int i = 0; i < [postDataChunk length] - l; i++)
{
//每次取两个字节 比对下看看是否是换行
NSRange searchRange = {i, l};
//假设是换行符则进行例如以下处理
if ([[postDataChunk subdataWithRange:searchRange] isEqualToData:separatorData])
{
//获取dataStartIndex标识的上一个换行位置到当前换行符之间的数据的Range
NSRange newDataRange = {dataStartIndex, i - dataStartIndex};
//dataStartIndex标识的上一个换行位置到移到当前换行符位置
dataStartIndex = i + l;
i += l - 1;
//获取dataStartIndex标识的上一个换行位置到当前换行符之间的数据
NSData *newData = [postDataChunk subdataWithRange:newDataRange];
//假设newData不为空或还没有处理完multipart/form-data中表单变量值域则继续处理剩下的表单值域数据
if ([newData length] || ![self isBeginOfOctetStream])
{
if ([newData length]) {
[multipartData addObject:newData];
}
}
else
{
//将标识处理完multipart/form-data中表单变量值域的postHeaderOK变量设置为TRUE;
postHeaderOK = TRUE;
//这里临时写成硬编码 弊端:每次添加表单变量都要改这里的数值
//获取Content-Disposition: form-data; name="xxx"; filename="xxx"
NSString* postInfo = [[NSString alloc] initWithBytes:[[multipartData objectAtIndex:4] bytes]
length:[[multipartData objectAtIndex:4] length]
encoding:NSUTF8StringEncoding];
NSLog(@"postInfo is:%@", postInfo);
NSArray* postInfoComponents = [postInfo componentsSeparatedByString:@"; filename="];
postInfoComponents = [[postInfoComponents lastObject] componentsSeparatedByString:@"\""];
NSLog(@"postInfoComponents0 :%@",postInfoComponents);
if ([postInfoComponents count]<2)
{
return;
}
postInfoComponents = [[postInfoComponents objectAtIndex:1] componentsSeparatedByString:@"\\"];
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* filename = [documentPath stringByAppendingPathComponent:[postInfoComponents lastObject]];
NSLog(@"filename :%@",filename);
NSRange fileDataRange = {dataStartIndex, [postDataChunk length] - dataStartIndex};
[[NSFileManager defaultManager] createFileAtPath:filename contents:[postDataChunk subdataWithRange:fileDataRange] attributes:nil];
NSFileHandle *file = [[NSFileHandle fileHandleForUpdatingAtPath:filename] retain];
if (file)
{
[file seekToEndOfFile];
[multipartData addObject:file];
}
[postInfo release];
break;
}
}
}
}
else //表单值域已经处理过了 这之后的数据全是文件数据流
{
[(NSFileHandle*)[multipartData lastObject] writeData:postDataChunk];
}
float uploadProgress = (double)requestContentLengthReceived / requestContentLength;
//实际应用时 当前类的实例是相当于单例一样被引用(由于仅仅被实例化一次)
if (uploadProgress >= 1.0) {
postHeaderOK = NO;
[multipartData release];
multipartData = nil;
}
[[NSNotificationCenter defaultCenter] postNotificationName:UPLOAD_FILE_PROGRESS object:[NSNumber numberWithFloat:uploadProgress] userInfo:nil];
}
//检查是否已经处理完了multipart/form-data表单中的表单变量
- (BOOL) isBeginOfOctetStream
{
NSString *octetStreamFlag = @"Content-Type: application/octet-stream";
NSString *findData = [[NSString alloc] initWithData:(NSData *)[multipartData lastObject] encoding:NSUTF8StringEncoding];
for (NSData *d in multipartData) {
NSString *temp = [[[NSString alloc] initWithData:d encoding:NSUTF8StringEncoding] autorelease] ;
NSLog(@"multipartData items: %@", temp);
}
//假设已经处理完了multipart/form-data表单中的表单变量
if ( findData != nil && [findData length] > 0 )
{
NSLog(@"findData is :%@\n octetStreamFlag is :%@", findData, octetStreamFlag);
if ([octetStreamFlag isEqualToString:findData]) {
NSLog(@"multipart/form-data 变量值域数据处理完成");
[findData release];
return YES;
}
[findData release];
return NO;
}
return NO;
}
@end
基本的代码就在 processDataChunk,我们仅仅须要在这里面处理数据就可以
以上代码主要转自github上 https://github.com/willonboy/CocoaHTTPServer---multipart-form-data点击打开链接
大家能够下载源代码研究
下章将要解说 web js代码
cocoahttpserver使用具体解释(二)的更多相关文章
- Android 布局学习之——Layout(布局)具体解释二(常见布局和布局參数)
[Android布局学习系列] 1.Android 布局学习之--Layout(布局)具体解释一 2.Android 布局学习之--Layout(布局)具体解释二(常见布局和布局參数) ...
- {MySQL存储引擎介绍}一 存储引擎解释 二 MySQL存储引擎分类 三 不同存储引擎的使用
MySQL存储引擎介绍 MySQL之存储引擎 本节目录 一 存储引擎解释 二 MySQL存储引擎分类 三 不同存储引擎的使用 一 存储引擎解释 首先确定一点,存储引擎的概念是MySQL里面才有的,不是 ...
- openssl之EVP系列之5---EVP_Encrypt系列函数具体解释(二)
openssl之EVP系列之5---EVP_Encrypt系列函数详细解释(二) ---依据openssl doc/crypto/EVP_EncryptInit.pod和doc/ssleay.t ...
- Kafka具体解释二、怎样配置Kafka集群
Kafka集群配置比較简单,为了更好的让大家理解.在这里要分别介绍以下三种配置 单节点:一个broker的集群 单节点:多个broker的集群 多节点:多broker集群 一.单节点单broker实例 ...
- cocos2dx 解释二具体的启动过程:内存管理和回调
在上一篇的第二部分中.我们有一句代码待解释的: // Draw the Scene void CCDirector::drawScene(void) { -... //tick before ...
- logistic回归具体解释(二):损失函数(cost function)具体解释
有监督学习 机器学习分为有监督学习,无监督学习,半监督学习.强化学习.对于逻辑回归来说,就是一种典型的有监督学习. 既然是有监督学习,训练集自然能够用例如以下方式表述: {(x1,y1),(x2,y2 ...
- WmS具体解释(二)之怎样理解Window和窗体的关系?基于Android7.0源代码
上篇博客(WmS具体解释(一)之token究竟是什么?基于Android7.0源代码)中我们简要介绍了token的作用,这里涉及到的概念非常多,当中出现频率最高的要数Window和窗体这一对搭档了,那 ...
- Android清单文件具体解释(二) ---- 应用程序权限声明
我们知道,Android系统的各个模块提供了很强大的功能(比方电话,电源和设置等),通过使用这些功能.应用程序能够表现的更强大.更灵活.只是,使用这些功能并非无条件的.而是须要拥有一些权限.接下来,我 ...
- android动画具体解释二 属性动画原理
property动画是一个强大的框架,它差点儿能使你动画不论什么东西. 你能够定义一个动画来改变对象的不论什么属性,不论其是否被绘制于屏幕之上. 一个属性动画在一定时间内多次改变一个属性(对象的一个字 ...
随机推荐
- 双面女间谍第一至五季/全集Alias迅雷下载
本季第一至五季 Alias Season (2001-2005)看点:<双面女间谍>她在CIA拥有双重身份,是个美貌矫健的年轻女间谍,一个性感的女007.但在第一季中,讲述更多的却是她在间 ...
- Oracle初级性能优化总结
前言 关于对Oracle数据库查询性能优化的一个简要的总结. 从来数据库优化都是一项艰巨的任务.对于大数据量,访问频繁的系统,优化工作显得尤为重要.由于Oracle系统的灵活性.复杂性.性能问题的原因 ...
- RecyclerView常见问题解决方案,RecyclerView嵌套自动滚动,RecyclerView 高度设置wrap_content 无作用等问题
1,ScrollView或者RecyclerView1 嵌套RecyclerView2 进入页面自动跳转到recyclerView2上面页面会自动滚动貌似是RecyclerView 自动获得了焦点两 ...
- [Web 前端] 解决因inline-block元素导致的空白间距和元素下沉
cp from : https://www.jianshu.com/p/617e78a27c88 ** 前言: ** CSS 中的 display:inline-block 是笔者最为喜欢的元素之一, ...
- JavaScript中的方法、方法引用和参数
首先,我们来看一段代码,如果觉得不甚明白的,则本文会对你有益: var player = function (e) { return (function f(m) { ...
- UEFI与 Legacy BIOS两种启动模式详解
(1). UEFI启动模式 与 legacy启动模式 legacy启动模式: 就是这么多年来PC一直在使用的启动方式(从MBR中加载启动程序),UEFI BIOS作为一种新的BIOS自然也应该兼容这种 ...
- 我讨厌Apple Safari浏览器的一些地方。不想用
1. 书签栏 无法直接新建文件夹 2. 新建书签 无法新建文件夹 3.地址栏 不显示当前书签 是否已收藏! 4. 书签栏 移动书签,体验没有Chrome好. 5.书签栏 没有chrone的 " ...
- windows包管理器chocolatey
1.安装chocolatey打开cmd.exe执行@powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Obj ...
- 首个threejs项目-前端填坑指南【转】
http://www.cnblogs.com/pursues/p/5226807.html 第一次使用threejs到实际项目中,开始的时候心情有点小激动,毕竟是第一次嘛,然而做着做着就感受到这玩意水 ...
- cesium js学习一加载三维模型【转】
http://blog.csdn.net/tangyajun_168/article/details/50936698 最近项目中用到室外三维模型与室内三维地图交互,室外三维模型的加载我们采用了ces ...