提交POST请求的四种方法

分类: APPBET365 时间: 2025-10-18 23:47:44 作者: admin 阅读: 5408

web浏览器、服务器和相应的web应用程序都是通过HTTP协议相互通信的。HTTP使用的是可靠的数据传输协议,它能够确保数据在传输的过程中不会被损坏或产生混乱。Http请求方式有多重,最近遇到了关于post的一些问题,所以这里专注了解下post提交数据的几种方式。

HTTP应用程序发送的数据块就是HTTP报文,它以一些文本形式的元信息开头,这些元信息描述了报文的内容及含义。后面跟着可选的数据部分。

所有HTTP的报文可以分为两类:请求报文(request message)和响应报文(response message)。请求报文会向web服务器请求一个动作,响应报文会将请求的结果返回给客户端。请求报文和响应报文的基本报文结构相同。

请求报文结构:

123

响应报文结构:

123

HTTP协议规定POST提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么样的编码方式,所以开发者可以自主定义消息体的格式,只要最后发送的HTTP请求满足上面的格式就可以。

但是,数据发送出去后,还需要服务端可以解析成功才有意义。一般服务端的语言和框架都可以正常解析常见的数据格式。服务端通常是根据请求头(headers)中的Content-Type字段来获得请求中的消息主题是用何种方式编码,再对主题进行解析。所以POST提交数据的方式,主要是Content-Type和消息主体编码的方式。

application/jsonjson的请求头基本上已经很常见了。它用来告诉服务端消息主体是序列后的json字符串。由于JSON规范的流行,除了低版本的IE之外各大浏览器都原生支持JSON.stringify,服务端语言也都有处理JSON的函数。一些框架都已经默认支持了。

它的好处是,可以直接用json传输结构化的数据,相比其他只能键值对的传输方式,这一点非常有用。顺便说一句,现在Angular里面默认支持的传输方式直接是application/json,可以直接使用。例如:

1234567891011121314constructor( private http: HttpClient,) { this.http.post('http://baidu.com', { a: 1, c: { d: 5, e: 6, } }).subscribe(res => { console.log('res', res); });}

直接调用httpClient来发起一个请求,直接使用json传递参数,服务端可以直接获取json数据。

application/x-www-form-urlencoded浏览器的原生

表单,如果不设置enctype属性,那么最终就会以application/x-www-form-urlencoded方式提交数据。请求类似下面这样:

12Content-Type: application/x-www-form-urlencoded;charset=utf-8name=tony&age=18

这个提价方式,参数会以键值对的方式进行传输:key=value&key=value,另外,提交的数据的key和value都进行了url转码。大部分服务端语言都对这种方式有很好的支持。

那在angular中如何将表单的提交方式转换到这种提交呢?毕竟我们使用的HttpClient是用的fetch提交,而不是原生表单的提交方式。

首先,我们需要将post请求方的header报文里面的Content-Type字段设置为application/x-www-form-urlencoded:

1234567891011121314151617constructor( private http: HttpClient,) { }ngOnInit(): void { const params = { name: 1,};this.http.post('http//www.baidu.com', params, { headers: { 'Content-Type': 'application/x-www-form-urlencoded', }}).subscribe(res => { console.log('res', res);});}

在浏览器开发工具的NetWork里面查看的时候,会发现这个请求的Content-Type已经变成了application/x-www-form-urlencoded,参数那一块内容也变成了form-data。但是,你在服务器里面处理这个请求的时候,没法子接收到参数值的。为什么?因为虽然我们把请求方式变了,但是参数还是json。这里需要对参数也处理一下:

1234567891011121314const params = {name: 'tony', age: 18};const bodies = [];for (const key of Object.keys(params)) { if (params[key] !== null) { bodies.push(key + '=' + encodeURIComponent(params[key])); }}this.http.post('http//www.baidu.com', bodies.join('&'), { headers: { 'Content-Type': 'application/x-www-form-urlencoded', }}).subscribe(res => { console.log('res', res);});

这样,服务器里面可以接收到参数name=tony&age=18,然后就可以正常解析了。

但是,这样处理是很不方便的,在一个大应用里面,总不能每个请求都这样设置。建议写一个公共方法去处理参数格式化,然后在拦截器里面去处理header,这样可以方便的扩展:

1234567intercept(req: HttpRequest, next: HttpHandler): Observable> { const authReq = req.clone({ headers: req.headers.set('Content-Type', 'application/x-www-form-urlencoded'), }); } return next.handle(authReq);}

multipart/form-data当使用表单上传文件时,必须让

12345678910111213POST http://www.example.com HTTP/1.1Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA------WebKitFormBoundaryrGKCBY7qhFd3TrwAContent-Disposition: form-data; name="text"title------WebKitFormBoundaryrGKCBY7qhFd3TrwAContent-Disposition: form-data; name="file"; filename="chrome.png"Content-Type: image/pngPNG ... content of chrome.png ...------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

首先生成了一个个boundary(边界)用于分割不同的字段,为了避免与正文内容重复,boundary很长很复杂。然后Content-Type指明了数据是以multipart-data来编码,本次请求的boundary内容是什么。

这种方式一般用来上传文件。

enctype还支持text/plain,但用的非常少。

text/xmlxml的方式传递参数,太麻烦了,不常用,还是用json吧。哈哈哈哈。。。。😄

其实是最近在开发angular项目的时候,忽然遇到了使用form-data方式提交表单的问题,本来摸索摸索可以提交了,但是当我提交一个比较复杂的字符串的时候服务器老是接收不到,后面才发现是没有进行url编码,所以后端直接爆炸了。也是很囧,正好借助这个机会来梳理一下,同时也是个记录。

参考文章:https://imququ.com/post/four-ways-to-post-data-in-http.html

相关文章

7个小矮人的故事是杜撰吗?《山海经》记载的矮人族真的存在吗?

安卓软件下SH365 · 09-06 阅读 1065

一( )网应该填什么量词

安卓软件下SH365 · 07-24 阅读 2414

编程时绝对值用什么表示 MATLAB

365app安卓客户端下载 · 10-11 阅读 9411