坚持 成长 每日一篇
前言
ASIHTTPRequest框架作者已经停更,今日公司ASIHTTPRequest从项目移除需要重构使用了ASIHTTPRequest的代码,要想重构ASIHTTPRequest最好对ASIHTTPRequest有所了解。今日花了2天时间看了ASIHTTPRequest源码,以此博客作为一些理解纪录
内容
ASIHTTPRequest和ASIFormDataRequest的关系
FormDataRequest是继承了httpRequest,他主要是针HTTP协议四种常见的POST方式的multipart/form-data请求和application/x-www-form-urlencoded请求。四种常见的请求详情http://www.aikaiyuan.com/6324.html
对于ASIHTTPRequest大家并不陌生,类似于iOS系统自带的request,这里主要介绍ASIFormDataRequest原理
ASIFormDataRequest特有属性
- postData:用来保存非文件的数据
- fileData:用来保存文件的数据
- debugBodyString:只是用于纪录组件HttpPostBody过程错误日志信息,没有其他作用,设置Body时候并没有用他
- postFormat:这是一个枚举属性,决定post是以form-data格式还是url encode格式上传数据
- stringEncoding:对于DebugBodyString转data时候采用的是何种编码。
ASIFormDataRequest.m实现文件里面的主要方法解释
三种设置PostData情况
普通文本类型
//普通文本类型最终会在这里加入所有的数据
- (void)addPostValue:(id <NSObject>)value forKey:(NSString *)key
{
if (!key) {
return;
}
if (![self postData]) {
[self setPostData:[NSMutableArray array]];
}
NSMutableDictionary *keyValuePair = [NSMutableDictionary dictionaryWithCapacity:2];
[keyValuePair setValue:key forKey:@"key"];
[keyValuePair setValue:[value description] forKey:@"value"];
[[self postData] addObject:keyValuePair];
}
//此方法最终调用上面的addPostValue:forKey:来给postData添加字典,postData在构建PostBody时候会被用到
- (void)setPostValue:(id <NSObject>)value forKey:(NSString *)key
{
// Remove any existing value
NSUInteger i;
for (i=0; i<[[self postData] count]; i++) {
NSDictionary *val = [[self postData] objectAtIndex:i];
if ([[val objectForKey:@"key"] isEqualToString:key]) {
[[self postData] removeObjectAtIndex:i];
i--;
}
}
[self addPostValue:value forKey:key];
}
本地文件路径,最终添加是数据到fileData
//无论你是addFileValue还是setFileValue最终都会调用这个方法来组织文件数据
- (void)addFile:(NSString *)filePath withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key
{
BOOL isDirectory = NO;
BOOL fileExists = [[[[NSFileManager alloc] init] autorelease] fileExistsAtPath:filePath isDirectory:&isDirectory];
if (!fileExists || isDirectory) {
[self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileBuildingRequestType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"No file exists at %@",filePath],NSLocalizedDescriptionKey,nil]]];
}
// If the caller didn't specify a custom file name, we'll use the file name of the file we were passed
if (!fileName) {
fileName = [filePath lastPathComponent];
}
// If we were given the path to a file, and the user didn't specify a mime type, we can detect it from the file extension
if (!contentType) {
contentType = [ASIHTTPRequest mimeTypeForFileAtPath:filePath];
}
[self addData:filePath withFileName:fileName andContentType:contentType forKey:key];
}
最后一种就是用于如果你手中已经有了文件数据,可以通过下列方法组织到fileData里面,包括上面介绍的file方法最终也是屌用此方法来
- (void)addData:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key
{
if (![self fileData]) {
[self setFileData:[NSMutableArray array]]