iOS 使用AFNetworking的form表單請(qǐng)求

首先說(shuō)明下form表單請(qǐng)求颤专,是一種特殊的post請(qǐng)求纽哥,請(qǐng)求方式有application/x-www-form-urlencodedmultipart/form-data栖秕、application/json春塌。其中application/json就是我們常見(jiàn)的post請(qǐng)求,使用AFN直接請(qǐng)求即可簇捍。

下面開(kāi)始正式的內(nèi)容只壳,如何使用AFNetworking完成form表單請(qǐng)求

1、application/x-www-form-urlencoded

直接上代碼:

+ (AFHTTPSessionManager *)getManagerWithReqType:(requestType)reqType{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    if(reqType == REQ_Form){
        [manager.requestSerializer setValue:@"application/x-www-form-urlencoded;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    }else{
        manager.requestSerializer = [AFJSONRequestSerializer serializer];
        manager.responseSerializer = [AFJSONResponseSerializer serializer];
        [manager.requestSerializer setValue:@"application/json;text/html;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    }
    return manager;
}

這種form表單請(qǐng)求方式和我們常見(jiàn)的post請(qǐng)求方式垦写,只有這一個(gè)地方需要區(qū)別吕世,特別注意以下兩句不能出現(xiàn)在application/x-www-form-urlencoded請(qǐng)求方式中

manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];

剩下的部分和常見(jiàn)的post請(qǐng)求一致彰触,請(qǐng)求時(shí)只需要調(diào)用:

- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                             parameters:(nullable id)parameters
                                headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                               progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
                                success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

2梯投、multipart/form-data

目前個(gè)人在項(xiàng)目中遇到的情況,主要用于上傳二進(jìn)制文件,使用時(shí)只需要在常見(jiàn)post請(qǐng)求的基礎(chǔ)上分蓖,設(shè)置Content-Type為:

[manager.requestSerializer setValue:@"multipart/form-data; boundary=----WebKitFormBoundaryHzyefUottpz7ltKf"forHTTPHeaderField:@"Content-Type"];

在調(diào)用方法上稍有不同尔艇,multipart/form-data調(diào)用AFN的constructingBodyWithBlock方法:

- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                             parameters:(nullable id)parameters
                                headers:(nullable NSDictionary <NSString *, NSString *> *)headers
              constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
                               progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
                                success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

以上傳視頻為例:

+(void)uploadVideoUseAFN:(NSURL *)filePath andUrl:(NSString *)urlString{
    AFHTTPSessionManager *manager = [self getManager];
    
    /// 要上傳的二進(jìn)制文件
    NSData *videoData = [NSData dataWithContentsOfURL:filePath];

    /// 二進(jìn)制文件在服務(wù)器保存的路勁
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    formatter.dateFormat =@"yyyyMMddHHmmss";
    NSString *str = [formatter stringFromDate:[NSDate date]];
    NSString *fileName = [NSString stringWithFormat:@"%@.mp4", str];
    
    NSURLSessionDataTask *task = [manager POST:urlString parameters:nil headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        /// 拼接formdata
        [formData appendPartWithFileData:videoData
                                    name:@"myFile"
                                fileName:fileName
                                mimeType:@"video/mpeg"];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
    }];
    [task resume];
}
疑點(diǎn)1、關(guān)于mimeType的設(shè)置

使用AFNetworking不需要設(shè)置額外的參數(shù)(如Content-Disposition)么鹤,因?yàn)樵?code>AFNetworking完成form提交時(shí)终娃,下面的方法會(huì)自動(dòng)設(shè)置Content-Disposition@"form-data; name=\"%@\"; filename=\"%@\"

- (void)appendPartWithFileData:(NSData *)data
                          name:(NSString *)name
                      fileName:(NSString *)fileName
                      mimeType:(NSString *)mimeType;

覺(jué)得不妥的也可以查看appendPartWithFileData的具體實(shí)現(xiàn),會(huì)發(fā)現(xiàn)如下內(nèi)容:

[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
[mutableHeaders setValue:mimeType forKey:@"Content-Type"];

這里有一個(gè)痛點(diǎn)蒸甜,就是關(guān)于mimeType的設(shè)置棠耕,圖片和視頻都很方便,可以直接設(shè)置為image/jpg柠新、image/png窍荧、video/mpeg等(最好和后臺(tái)對(duì)一下,因?yàn)橛行╅_(kāi)發(fā)會(huì)指定文件類型恨憎,設(shè)置不一致會(huì)請(qǐng)求失敗)蕊退。

但對(duì)于文件上傳,mimeType設(shè)置什么就比較懵憔恳,這里可以設(shè)置萬(wàn)能類型application/octet-stream瓤荔,服務(wù)器會(huì)自動(dòng)解析文件類型。關(guān)于如何獲取文件的mimeType钥组,可以查看

疑點(diǎn)2输硝、關(guān)于使用AFNetworking提交Form表單,請(qǐng)求成功了程梦,但是后臺(tái)接收到的數(shù)據(jù)為空

正常情況下我們使用form提交腔丧,都會(huì)在header中設(shè)置:

[manager.requestSerializer setValue:@"multipart/form-data; boundary=----WebKitFormBoundaryHzyefUottpz7ltKf"forHTTPHeaderField:@"Content-Type"];

后臺(tái)沒(méi)有接收到傳過(guò)去的數(shù)據(jù)就是因?yàn)樵O(shè)置了multipart/form-databoundary。這里最坑的就是設(shè)置了multipart/form-databoundary作烟,還能請(qǐng)求成功愉粤,讓人一度人為自己寫的代碼沒(méi)有半點(diǎn)毛病。

解決辦法:

+ (void)uploadImageWIthimageData:(NSData *)imageData{
    NSString *requestUrl = @"";
    
    /// 設(shè)置filename
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    formatter.dateFormat =@"yyyyMMddHHmmss";
    NSString *str = [formatter stringFromDate:[NSDate date]];
    NSString *fileName = [NSString stringWithFormat:@"%@.jpg", str];
    
    /// 請(qǐng)求配置
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    /// 注意:如果返回結(jié)果是json類型按如下設(shè)置拿撩,data類型manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/html",@"image/jpeg",@"image/png",@"application/octet-stream",@"text/json",nil];
    
    /// 設(shè)置上傳參數(shù)衣厘,經(jīng)過(guò)測(cè)試這個(gè)可以不用傳
    NSDictionary *params = @{@"file":imageData};
    
    /// 設(shè)置header
    NSDictionary *headers = @{@"Authorization":@""};
    
    NSURLSessionDataTask *task = [manager POST:requestUrl parameters:params headers:headers constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        [formData appendPartWithFileData:imageData
                                    name:@"file"
                                fileName:fileName
                                mimeType:@"image/jpg"];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    }];
    [task resume];
}

你也不要覺(jué)得這樣就不是一個(gè)multipart/form-data類型的請(qǐng)求了,因?yàn)?code>AFNetworking會(huì)自動(dòng)補(bǔ)全這一部分

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末压恒,一起剝皮案震驚了整個(gè)濱河市影暴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌探赫,老刑警劉巖型宙,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異伦吠,居然都是意外死亡妆兑,警方通過(guò)查閱死者的電腦和手機(jī)魂拦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)搁嗓,“玉大人芯勘,你說(shuō)我怎么就攤上這事∠俟洌” “怎么了荷愕?”我有些...
    開(kāi)封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)棍矛。 經(jīng)常有香客問(wèn)我安疗,道長(zhǎng),這世上最難降的妖魔是什么够委? 我笑而不...
    開(kāi)封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任茂契,我火速辦了婚禮,結(jié)果婚禮上慨绳,老公的妹妹穿的比我還像新娘掉冶。我一直安慰自己,他們只是感情好脐雪,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布厌小。 她就那樣靜靜地躺著,像睡著了一般战秋。 火紅的嫁衣襯著肌膚如雪璧亚。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天脂信,我揣著相機(jī)與錄音癣蟋,去河邊找鬼。 笑死狰闪,一個(gè)胖子當(dāng)著我的面吹牛疯搅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播埋泵,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼幔欧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了丽声?” 一聲冷哼從身側(cè)響起礁蔗,我...
    開(kāi)封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎雁社,沒(méi)想到半個(gè)月后浴井,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霉撵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年磺浙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了洪囤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡屠缭,死狀恐怖箍鼓,靈堂內(nèi)的尸體忽然破棺而出崭参,到底是詐尸還是另有隱情呵曹,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布何暮,位于F島的核電站奄喂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏海洼。R本人自食惡果不足惜跨新,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坏逢。 院中可真熱鬧域帐,春花似錦、人聲如沸是整。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)浮入。三九已至龙优,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間事秀,已是汗流浹背彤断。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留易迹,地道東北人宰衙。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像睹欲,于是被迫代替她去往敵國(guó)和親菩浙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容