1. 程式人生 > >cocoahttpserver使用具體解釋(二)

cocoahttpserver使用具體解釋(二)

ons track pro 下載 app 實例 添加 == 兩個

接下來,我們接著去學習怎樣去接收處理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使用具體解釋(二)