不用form-data(也就是表單)傳流 直接用post傳參的形式傳遞流
這里面我們介紹的是第三方框架 AFNetworking:
AFNetworking是一個輕量級的iOS網絡通信類庫。它建立在NSURLConnection和NSOperation等類庫的基礎上,讓很多網絡通信功能的實現變得十分簡單。它支持HTTP請求和基於REST的網絡服務(包括GET、POST、 PUT、DELETE等)。支持ARC,不帶上這句感覺沒頭沒尾的。
1.首先 所有的網絡請求,均有manager發起
AFHTTPRequestOperationManager *manager=[AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
需要注意的是,默認提交請求的數據是二進制的,返回格式是JSON
1> 如果提交數據是JSON的,需要將請求格式設置為AFJSONRequestSerializer
2> 如果返回格式不是JSON的,
2. 請求格式
AFHTTPRequestSerializer 二進制格式
AFJSONRequestSerializer JSON
AFPropertyListRequestSerializer PList(是一種特殊的XML,解析起來相對容易)
說到這里就說下自己陷入的誤區 iOS客戶端這塊是直接傳遞流的也就是(NSData)
但是AF的 AFHTTPRequestSerializer 和 AFJSONRequestSerializer是傳遞有區分
AFHTTPRequestSerializer的傳遞 在底層又對 參數和參數值進行了一次Url編碼
>>>>>>[mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
AFJSONRequestSerializer的傳遞 則是在底層將 參數(一般情況下我們傳遞的是字典類型 也就是java中的map形式)轉化為了NSData類型進行傳遞
>>>>>>[mutableRequest setHTTPBody:[NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]];
由於此時我的項目要求直接傳遞NSData(id+手機號+圖片流)此時的NSData是用NSMutableData 所以在底層 就不需要再次的轉化一次data
此時我修改代碼為
>>>>>>[mutableRequest setHTTPBody:parameters];
這樣我就可以直接用json形式直接傳遞服務端所需要的NSData 沒有包含form-data里面所攜帶的參數 因為這些參數服務端那邊代碼解析會出現問題
我猜測服務端用的不是主流的解析框架
介紹完了請求對象方式屬性 下面來說下傳遞參數的屬性
一般的網絡請求分為2種也就是mimeType的2種類型
1.application/x-www-form-urlencoded
2.multipart/form-data(最初的 http 協議中,沒有上傳文件方面的功能。rfc1867為http協議添加了這個功能)也就是Multipart協議
>>>>>>絕大部分 http server ,包括 tomcat ,已經支持此協議,可接受發送來的文件。各種網頁程序,如 php, asp, jsp 中,對於上傳文件已經做了很好的封裝
但是我猜測我們服務端並未使用這種方式
>>>>>>我們先查看這個協議的結構 以下是別人的概述:
--${bound} // 該bound表示pdf的文件名
Content-Disposition: form-data; name="Filename"
HTTP.pdf
--${bound} // 該bound表示pdf的文件內容
Content-Disposition: form-data; name="file000"; filename="HTTP協議詳解.pdf"
Content-Type: application/octet-stream
%PDF-1.5
file content
%%EOF
--${bound} // 該bound表示字符串
Content-Disposition: form-data; name="Upload"
Submit Query
--${bound}—// 表示body結束了
>>>>>>>> request是由三個部分組成的:①請求行(request-line) ②請求頭(headers) ③請求體(request body)
構建multipart請求行 就是POST。
構建multipart請求頭
@property (nonatomic, copy) NSString *boundary; // multipart協議中的分割符
boundary是用來分割不同數據內容的,其實就是上面舉的那個例子中的${bound}
AFNetworking自定義了個函數創建boundary字符串
1.如果是開頭分隔符的,那么只需在分隔符結尾加一個換行符
2.如果是中間部分分隔符,那么需要分隔符前面和結尾都加換行符
3.如果是末尾,還得使用--分隔符--作為請求體的結束標志
他的作用除了設置Content-Type外,在設置Content-Length時使用的[self.bodyStream contentLength]中會使用到 boundary的
我的經歷就是當時用的是form-data傳遞 但是可能后台沒用主流解析框架 導致 解析不出我所傳遞的 NSData 然后顯示的解析除了 --boundary+開頭的字段
所以此時我就果斷拋棄了使用 form-data
改用application/x-www-form-urlencoded的網絡和AFJSONRequestSerializer(修改底層不用再次轉化一次data)結合的方式 直接將data類型的傳遞至服務端
至此 自己的坑比生涯結束
有些寫的不太詳細 有什么不對 還望各位指點 謝謝
