文章結構
1.http客戶端常用的請求方式
multipart/form-data
傳數(shù)組各個終端的實現(xiàn)方式以及后臺怎么處理拿到的數(shù)據(jù)2.1 web端
2.2 安卓端(OKHTTP)
2.3 蘋果端(AFNetworking)
2.4 后臺處理拿到的數(shù)據(jù)
一、http請求常用的兩種方式post/get
HTTP請求方式有OPTIONS作郭、GET阿逃、HEAD斥黑、POST凌节、PUT施掏、DELETE谎倔、TRACE鸟辅、CONNECT
具體的http
請求方式種類見這篇文章:
HTTP深入淺出 http請求
HTTP協(xié)議詳解
通常我們用的只有GET氛什、POST
常用的POST請求,按照content-Type
來分匪凉,又分為 application/x-www-form-urlencoded
枪眉、multipart/form-data
、application/json
這幾種再层。
具體的content-Type
介紹可以看這篇文章:
理解HTTP之Content-Type
get 與post請求方式的區(qū)別就不細講了贸铜,這里我們看下HTTP1.1版本協(xié)議里面規(guī)定的一個標準的HTTP請求格式應該包含的內(nèi)容:
1.1 HTTP請求格式:
請求方法URI協(xié)議/版本
請求頭(Request Header)
請求正文
例子:
GET/sample.jspHTTP/1.1
Accept:image/gif.image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
Accept-Encoding:gzip,deflate
username=jinqiao&password=1234
1.2 Content-Type幾個常見的類型
1.text/html
2.text/plain
3.text/css
4.text/javascript
5.application/x-www-form-urlencoded
6.multipart/form-data
7.application/json
8.application/xml
1.2.1 app常用的三種類型:
(1)application/x-www-form-urlencoded
application/x-www-form-urlencoded是常用的表單發(fā)包方式,普通的表單提交聂受,或者js發(fā)包蒿秦,默認都是通過這種方式, body以這樣的方式傳輸 name=homeway&key=nokey
如下:
(2)multipart/form-data
這里
Content-Type
告訴我們,發(fā)包是以multipart/form-data
格式來傳輸蛋济,另外棍鳖,還有boundary
用于分割數(shù)據(jù),具體的boundary
由客戶端自定,在header
中以boundary
字段返回給服務端碗旅。
當文件太長鹊杖,HTTP無法在一個包之內(nèi)發(fā)送完畢,就需要分割數(shù)據(jù)扛芽,分割成一個一個chunk
發(fā)送給服務端
那么--
用于區(qū)分數(shù)據(jù)快,而后面的數(shù)據(jù)633e61ebf351484f9124d63ce76d8469
就是標示區(qū)分包作用积瞒。
(3)application/json
在body中參數(shù)會以json
字符串的形式川尖,傳送出去。如下所示。
二叮喳、multipart/form-data
傳數(shù)組各個終端的實現(xiàn)方式以及后臺怎么處理拿到的數(shù)據(jù)
2.1 web端
<input type="hidden" name="cars[]" value="Volvo">
<input type="hidden" name="cars[]" value="Saab">
<input type="hidden" name="cars[]" value="Mercedes">
以上代碼被芳,可以看出 HTML 傳遞數(shù)組 就是把參數(shù)寫成數(shù)組的形式,進行傳遞馍悟。
最終上傳的值會像這樣:
How to pass an array within a query string?
2.2 安卓端(OKHTTP)
這里是 截取的 postman
使用數(shù)組參數(shù) 進行的請求頭的參數(shù)畔濒。
所以 我們只需要在代碼中找到 對應的API 就可以了。按照這個區(qū)拼接 HTTP
的請求锣咒。
我這里 是使用的 okHTTP
private void addParams(MultipartBody.Builder builder) {
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + key.replaceAll("\\[\\d+\\]", "") + "\""),
RequestBody.create(null, params.get(key)));
}
}
}
然后就OK了
html
這樣寫 有可能就是為了拼接這個才這樣寫的侵状。 在postman中嘗試,完美解決阿浓。傳遞過去 因為有 數(shù)組的標示[ ]
會把這個強轉(zhuǎn)成數(shù)組嫁艇。
2.3 蘋果端(AFNetworking)
上面有提到根據(jù)content-Type
有以下三種常用的類型
1.application/x-www-form-urlencoded
2.multipart/form-data
3.application/json
我們再看下AFNetWorking
+ (void)postWithURL:(NSString *)url params:(NSDictionary *)params progress:(void (^)(id))progress success:(void (^)(id))success failure:(void (^)(NSError *))failure
{
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
mgr.requestSerializer.timeoutInterval = 20.0f;
NSLog(@"url:%@\nparas:%@",url,params);
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[mgr POST:url parameters:params progress:^(NSProgress * _Nonnull uploadProgress) {
progress?progress(uploadProgress):nil;
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
success?success(responseObject):nil;
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
failure?failure(error):nil;
}];
}
官方給出來的三個請求類:
對應的content-Type類型如上致开,請求在不指定請求序列化類時默認用的第一種。第三種主要是對xml
類型傳輸方式的支持艇潭,感興趣的朋友可以自己查閱下。
要切換請求
content-Type
到application/json
方式很簡單戏蔑,直接上代碼蹋凝。
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
mgr.requestSerializer.timeoutInterval = 8.0f;
NSString *token = [faceTokenMannage shareMannager].token;
mgr.requestSerializer = [AFJSONRequestSerializer serializer];
[mgr.requestSerializer setValue:token forHTTPHeaderField:@"Authorization"];
2.3.2 multipart/form-data
我們平時主要用來傳文件的函數(shù)
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(id)parameters
constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
看下內(nèi)部的實現(xiàn)方式:
點擊跳轉(zhuǎn)
再跳轉(zhuǎn)
可以發(fā)現(xiàn)這里對數(shù)組的處理是類似的,[]
.
分別用afnet 以 multipart/form-data
的方式傳純屬組总棵,以及字典數(shù)組鳍寂,抓包采集的結果如下:
純數(shù)組:
[name1,name2]
字典數(shù)組:
[{ID:peo1,name:ni},{ID:peo2,name:ni2}]
抓包結果
2.4 后臺處理拿到的數(shù)據(jù)
@RequestMapping("/uploadImage")
public @ResponseBody FeedResult uploadImage(HttpServletRequest request, UploadFileForm form) {
FeedResult f = new FeedResult();
//純數(shù)組
String[]ids = request.getParameterValues("groups[]");
//數(shù)組對象
String[]ids = request.getParameterValues("groups_id[]");
String[]names = request.getParameterValues("groups_name[]");
try {
f = FileUploadUtil.handleUploadFile(form, true);
return f;
} catch (Exception e) {
log.error(e.getMessage(), e);
return f.error("文件上傳失敗");
}
}