MyHTTPConnection.m
上传用户:kc0325
上传日期:2020-06-20
资源大小:204k
文件大小:9k
源码类别:

iPhone

开发平台:

Objective-C

  1. //
  2. //  This class was created by Nonnus,
  3. //  who graciously decided to share it with the CocoaHTTPServer community.
  4. //
  5. #import "MyHTTPConnection.h"
  6. #import "HTTPServer.h"
  7. #import "HTTPResponse.h"
  8. #import "AsyncSocket.h"
  9. @implementation MyHTTPConnection
  10. /**
  11.  * Returns whether or not the requested resource is browseable.
  12. **/
  13. - (BOOL)isBrowseable:(NSString *)path
  14. {
  15. // Override me to provide custom configuration...
  16. // You can configure it for the entire server, or based on the current request
  17. return YES;
  18. }
  19. /**
  20.  * This method creates a html browseable page.
  21.  * Customize to fit your needs
  22. **/
  23. - (NSString *)createBrowseableIndex:(NSString *)path
  24. {
  25.     NSArray *array = [[NSFileManager defaultManager] directoryContentsAtPath:path];
  26.     
  27.     NSMutableString *outdata = [NSMutableString new];
  28. [outdata appendString:@"<html><head>"];
  29. [outdata appendFormat:@"<title>Files from %@</title>", server.name];
  30.     [outdata appendString:@"<style>html {background-color:#eeeeee} body { background-color:#FFFFFF; font-family:Tahoma,Arial,Helvetica,sans-serif; font-size:18x; margin-left:15%; margin-right:15%; border:3px groove #006600; padding:15px; } </style>"];
  31.     [outdata appendString:@"</head><body>"];
  32. [outdata appendFormat:@"<h1>Files from %@</h1>", server.name];
  33.     [outdata appendString:@"<bq>The following files are hosted live from the iPhone's Docs folder.</bq>"];
  34.     [outdata appendString:@"<p>"];
  35. [outdata appendFormat:@"<a href="..">..</a><br />n"];
  36.     for (NSString *fname in array)
  37.     {
  38.         NSDictionary *fileDict = [[NSFileManager defaultManager] fileAttributesAtPath:[path stringByAppendingPathComponent:fname] traverseLink:NO];
  39. //NSLog(@"fileDict: %@", fileDict);
  40.         NSString *modDate = [[fileDict objectForKey:NSFileModificationDate] description];
  41. if ([[fileDict objectForKey:NSFileType] isEqualToString: @"NSFileTypeDirectory"]) fname = [fname stringByAppendingString:@"/"];
  42. [outdata appendFormat:@"<a href="%@">%@</a> (%8.1f Kb, %@)<br />n", fname, fname, [[fileDict objectForKey:NSFileSize] floatValue] / 1024, modDate];
  43.     }
  44.     [outdata appendString:@"</p>"];
  45. if ([self supportsPOST:path withSize:0])
  46. {
  47. [outdata appendString:@"<form action="" method="post" enctype="multipart/form-data" name="form1" id="form1">"];
  48. [outdata appendString:@"<label>upload file"];
  49. [outdata appendString:@"<input type="file" name="file" id="file" />"];
  50. [outdata appendString:@"</label>"];
  51. [outdata appendString:@"<label>"];
  52. [outdata appendString:@"<input type="submit" name="button" id="button" value="Submit" />"];
  53. [outdata appendString:@"</label>"];
  54. [outdata appendString:@"</form>"];
  55. }
  56. [outdata appendString:@"</body></html>"];
  57.     
  58. //NSLog(@"outData: %@", outdata);
  59.     return [outdata autorelease];
  60. }
  61. - (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)relativePath
  62. {
  63. if ([@"POST" isEqualToString:method])
  64. {
  65. return YES;
  66. }
  67. return [super supportsMethod:method atPath:relativePath];
  68. }
  69. /**
  70.  * Returns whether or not the server will accept POSTs.
  71.  * That is, whether the server will accept uploaded data for the given URI.
  72. **/
  73. - (BOOL)supportsPOST:(NSString *)path withSize:(UInt64)contentLength
  74. {
  75. // NSLog(@"POST:%@", path);
  76. dataStartIndex = 0;
  77. multipartData = [[NSMutableArray alloc] init];
  78. postHeaderOK = FALSE;
  79. return YES;
  80. }
  81. /**
  82.  * This method is called to get a response for a request.
  83.  * You may return any object that adopts the HTTPResponse protocol.
  84.  * The HTTPServer comes with two such classes: HTTPFileResponse and HTTPDataResponse.
  85.  * HTTPFileResponse is a wrapper for an NSFileHandle object, and is the preferred way to send a file response.
  86.  * HTTPDataResopnse is a wrapper for an NSData object, and may be used to send a custom response.
  87. **/
  88. - (NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path
  89. {
  90. NSLog(@"httpResponseForURI: method:%@ path:%@", method, path);
  91. NSData *requestData = [(NSData *)CFHTTPMessageCopySerializedMessage(request) autorelease];
  92. NSString *requestStr = [[[NSString alloc] initWithData:requestData encoding:NSASCIIStringEncoding] autorelease];
  93. NSLog(@"n=== Request ====================n%@n================================", requestStr);
  94. if (requestContentLength > 0)  // Process POST data
  95. {
  96. NSLog(@"processing post data: %i", requestContentLength);
  97. if ([multipartData count] < 2) return nil;
  98. NSString* postInfo = [[NSString alloc] initWithBytes:[[multipartData objectAtIndex:1] bytes]
  99.   length:[[multipartData objectAtIndex:1] length]
  100. encoding:NSUTF8StringEncoding];
  101. NSArray* postInfoComponents = [postInfo componentsSeparatedByString:@"; filename="];
  102. postInfoComponents = [[postInfoComponents lastObject] componentsSeparatedByString:@"""];
  103. postInfoComponents = [[postInfoComponents objectAtIndex:1] componentsSeparatedByString:@"\"];
  104. NSString* filename = [postInfoComponents lastObject];
  105. if (![filename isEqualToString:@""]) //this makes sure we did not submitted upload form without selecting file
  106. {
  107. UInt16 separatorBytes = 0x0A0D;
  108. NSMutableData* separatorData = [NSMutableData dataWithBytes:&separatorBytes length:2];
  109. [separatorData appendData:[multipartData objectAtIndex:0]];
  110. int l = [separatorData length];
  111. int count = 2; //number of times the separator shows up at the end of file data
  112. NSFileHandle* dataToTrim = [multipartData lastObject];
  113. NSLog(@"data: %@", dataToTrim);
  114. for (unsigned long long i = [dataToTrim offsetInFile] - l; i > 0; i--)
  115. {
  116. [dataToTrim seekToFileOffset:i];
  117. if ([[dataToTrim readDataOfLength:l] isEqualToData:separatorData])
  118. {
  119. [dataToTrim truncateFileAtOffset:i];
  120. i -= l;
  121. if (--count == 0) break;
  122. }
  123. }
  124. NSLog(@"NewFileUploaded");
  125. [[NSNotificationCenter defaultCenter] postNotificationName:@"NewFileUploaded" object:nil];
  126. }
  127. for (int n = 1; n < [multipartData count] - 1; n++)
  128. NSLog(@"%@", [[NSString alloc] initWithBytes:[[multipartData objectAtIndex:n] bytes] length:[[multipartData objectAtIndex:n] length] encoding:NSUTF8StringEncoding]);
  129. [postInfo release];
  130. [multipartData release];
  131. requestContentLength = 0;
  132. }
  133. NSString *filePath = [self filePathForURI:path];
  134. if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
  135. {
  136. return [[[HTTPFileResponse alloc] initWithFilePath:filePath] autorelease];
  137. }
  138. else
  139. {
  140. NSString *folder = [path isEqualToString:@"/"] ? [[server documentRoot] path] : [NSString stringWithFormat: @"%@%@", [[server documentRoot] path], path];
  141. if ([self isBrowseable:folder])
  142. {
  143. //NSLog(@"folder: %@", folder);
  144. NSData *browseData = [[self createBrowseableIndex:folder] dataUsingEncoding:NSUTF8StringEncoding];
  145. return [[[HTTPDataResponse alloc] initWithData:browseData] autorelease];
  146. }
  147. }
  148. return nil;
  149. }
  150. /**
  151.  * This method is called to handle data read from a POST.
  152.  * The given data is part of the POST body.
  153. **/
  154. - (void)processDataChunk:(NSData *)postDataChunk
  155. {
  156. // Override me to do something useful with a POST.
  157. // If the post is small, such as a simple form, you may want to simply append the data to the request.
  158. // If the post is big, such as a file upload, you may want to store the file to disk.
  159. // 
  160. // Remember: In order to support LARGE POST uploads, the data is read in chunks.
  161. // This prevents a 50 MB upload from being stored in RAM.
  162. // The size of the chunks are limited by the POST_CHUNKSIZE definition.
  163. // Therefore, this method may be called multiple times for the same POST request.
  164. //NSLog(@"processPostDataChunk");
  165. if (!postHeaderOK)
  166. {
  167. UInt16 separatorBytes = 0x0A0D;
  168. NSData* separatorData = [NSData dataWithBytes:&separatorBytes length:2];
  169. int l = [separatorData length];
  170. for (int i = 0; i < [postDataChunk length] - l; i++)
  171. {
  172. NSRange searchRange = {i, l};
  173. if ([[postDataChunk subdataWithRange:searchRange] isEqualToData:separatorData])
  174. {
  175. NSRange newDataRange = {dataStartIndex, i - dataStartIndex};
  176. dataStartIndex = i + l;
  177. i += l - 1;
  178. NSData *newData = [postDataChunk subdataWithRange:newDataRange];
  179. if ([newData length])
  180. {
  181. [multipartData addObject:newData];
  182. }
  183. else
  184. {
  185. postHeaderOK = TRUE;
  186. NSString* postInfo = [[NSString alloc] initWithBytes:[[multipartData objectAtIndex:1] bytes] length:[[multipartData objectAtIndex:1] length] encoding:NSUTF8StringEncoding];
  187. NSArray* postInfoComponents = [postInfo componentsSeparatedByString:@"; filename="];
  188. postInfoComponents = [[postInfoComponents lastObject] componentsSeparatedByString:@"""];
  189. postInfoComponents = [[postInfoComponents objectAtIndex:1] componentsSeparatedByString:@"\"];
  190. NSString* filename = [[[server documentRoot] path] stringByAppendingPathComponent:[postInfoComponents lastObject]];
  191. NSRange fileDataRange = {dataStartIndex, [postDataChunk length] - dataStartIndex};
  192. [[NSFileManager defaultManager] createFileAtPath:filename contents:[postDataChunk subdataWithRange:fileDataRange] attributes:nil];
  193. NSFileHandle *file = [[NSFileHandle fileHandleForUpdatingAtPath:filename] retain];
  194. if (file)
  195. {
  196. [file seekToEndOfFile];
  197. [multipartData addObject:file];
  198. }
  199. [postInfo release];
  200. break;
  201. }
  202. }
  203. }
  204. }
  205. else
  206. {
  207. [(NSFileHandle*)[multipartData lastObject] writeData:postDataChunk];
  208. }
  209. }
  210. @end