現(xiàn)在我們經(jīng)常用到請(qǐng)求數(shù)據(jù)的方式是http+json方式,但是,在某些情況下,后臺(tái)提供給你的方式是http的表單請(qǐng)求方式,今天就總結(jié)一下表單請(qǐng)求方式的實(shí)現(xiàn)。
先來(lái)看一下表單的一般形式:
3491AF42-5C81-448B-B7BB-5C776C551507.png
在表單中,我們需要注意的有以下幾點(diǎn):
- 1.我們需要自己設(shè)置Content-Type和Content-Length
- 2.在表單中,boundary是一個(gè)很重要的東西,他可以是一個(gè)隨機(jī)的字符串,它是將參數(shù)隔開(kāi)的標(biāo)志,但需要注意的是,這個(gè)標(biāo)志在整個(gè)表單中必須一致
- 3.我們?cè)谠O(shè)置參數(shù)時(shí),需要指定Content-Disposition,其中,name為參數(shù)對(duì)于的key值。如果參數(shù)為文件格式,同時(shí)還要指定filename以及Content-Type
- 4.其中最重要的一點(diǎn),就是在設(shè)置參數(shù)的value時(shí),必須在值之前加入一個(gè)換行。同時(shí),在http中,換行為\r\n
- 5.參數(shù)的分隔是以"--"拼接上boundary,然后拼接上"\r\n"來(lái)實(shí)現(xiàn)的,同時(shí),在所有參數(shù)結(jié)束后,需要以"--"拼接boundary再拼接"--"來(lái)結(jié)束。
接下來(lái)寫(xiě)一個(gè)簡(jiǎn)短的例子來(lái)記錄用法,在這個(gè)例子中,接口需要傳入兩個(gè)參數(shù),一個(gè)為簡(jiǎn)單的參數(shù),另一個(gè)為文件參數(shù)。
- 1.我們可以自己拼接出表單形式
//接口地址
NSString *path = kURL;
//boundary
NSString *theBoundary = @"myBoundary";
//訪問(wèn)請(qǐng)求
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:path]];
request.HTTPMethod = @"POST";
//用來(lái)拼接參數(shù)
NSMutableData *data = [NSMutableData data];
//拼接第一個(gè)參數(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]];
//拼接第二個(gè)參數(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]];
//拼接文件類(lèi)型
[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ò)請(qǐng)求,就不能忘掉強(qiáng)大的AFN,AFN提供了表單的請(qǐng)求方法,下圖是AFN主頁(yè)所講:
C3875D2B-96D8-4BD3-8766-BBF0CB665228.png
我們可以用AFN來(lái)實(shí)現(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];
注意,有時(shí)可能會(huì)報(bào)以下錯(cuò)誤:
B21632C2-15F0-4AF7-A480-38154DB5B320.png
這里我們可以去工程中查找AFN的源碼,其中有一個(gè)文件為:AFURLResponseSerialization.m,我們?cè)诘?20行左右做一些修改,將所缺少類(lèi)型加上即可:
修改前:
self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];
修改后:
self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/plain", nil];