現(xiàn)在我們經(jīng)常用到請求數(shù)據(jù)的方式是http+json方式四濒,但是歼捐,在某些情況下,后臺提供給你的方式是http的表單請求方式率触,今天就總結(jié)一下表單請求方式的實現(xiàn)。
先來看一下表單的一般形式:
3491AF42-5C81-448B-B7BB-5C776C551507.png
在表單中汇竭,我們需要注意的有以下幾點:
- 1.我們需要自己設(shè)置Content-Type和Content-Length
- 2.在表單中葱蝗,boundary是一個很重要的東西,他可以是一個隨機的字符串细燎,它是將參數(shù)隔開的標(biāo)志两曼,但需要注意的是,這個標(biāo)志在整個表單中必須一致
- 3.我們在設(shè)置參數(shù)時玻驻,需要指定Content-Disposition合愈,其中,name為參數(shù)對于的key值击狮。如果參數(shù)為文件格式,同時還要指定filename以及Content-Type
- 4.其中最重要的一點益老,就是在設(shè)置參數(shù)的value時彪蓬,必須在值之前加入一個換行。同時捺萌,在http中档冬,換行為\r\n
- 5.參數(shù)的分隔是以"--"拼接上boundary,然后拼接上"\r\n"來實現(xiàn)的桃纯,同時酷誓,在所有參數(shù)結(jié)束后,需要以"--"拼接boundary再拼接"--"來結(jié)束态坦。
接下來寫一個簡短的例子來記錄用法盐数,在這個例子中,接口需要傳入兩個參數(shù)伞梯,一個為簡單的參數(shù)玫氢,另一個為文件參數(shù)。
- 1.我們可以自己拼接出表單形式
//接口地址
NSString *path = kURL;
//boundary
NSString *theBoundary = @"myBoundary";
//訪問請求
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:path]];
request.HTTPMethod = @"POST";
//用來拼接參數(shù)
NSMutableData *data = [NSMutableData data];
//拼接第一個參數(shù)
[data appendData:[[NSString stringWithFormat:@"--%@\r\n", theBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
//拼接參數(shù)名
[data appendData:[@"Content-Disposition:form-data;name=\"uid\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
//拼接參數(shù)值
[data appendData:[@"11230953" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
//拼接第二個參數(shù)
[data appendData:[[NSString stringWithFormat:@"--%@\r\n", theBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
//拼接參數(shù)名
[data appendData:[@"Content-Disposition:form-data;name=\"file\";filename=\"myText.txt\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
//拼接文件類型
[data appendData:[@"Content-Type:text/plain" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
//拼接參數(shù)值
[data appendData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"myText" ofType:@"txt"]]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
//拼接結(jié)束標(biāo)志
[data appendData:[[NSString stringWithFormat:@"--%@--", theBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
request.HTTPBody = data;
[request setValue:[NSString stringWithFormat:@"multipart/form-data;boundary=%@", theBoundary] forHTTPHeaderField:@"Content-Type"];
[request setValue:[NSString stringWithFormat:@"%ld", data.length] forHTTPHeaderField:@"Content-Length"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@", dic);
}];
[dataTask resume];
- 2.既然是網(wǎng)絡(luò)請求谜诫,就不能忘掉強大的AFN漾峡,AFN提供了表單的請求方法,下圖是AFN主頁所講:
C3875D2B-96D8-4BD3-8766-BBF0CB665228.png
我們可以用AFN來實現(xiàn)上述接口的傳參:
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:kURL parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFormData:[@"11230953" dataUsingEncoding:NSUTF8StringEncoding] name:@"uid"];
[formData appendPartWithFileData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"myText" ofType:@"txt"]] name:@"file" fileName:@"myText.txt" mimeType:@"text/plain"];
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager
uploadTaskWithStreamedRequest:request
progress:^(NSProgress * _Nonnull uploadProgress) {
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"%@ %@", response, responseObject);
}
}];
[uploadTask resume];
注意喻旷,有時可能會報以下錯誤:
B21632C2-15F0-4AF7-A480-38154DB5B320.png
這里我們可以去工程中查找AFN的源碼生逸,其中有一個文件為:AFURLResponseSerialization.m,我們在第220行左右做一些修改,將所缺少類型加上即可:
修改前:
self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];
修改后:
self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/plain", nil];