健忘,故笔记
更新
2017-12-8
:经/\/\
提醒,GET
数据编码部分有误,已改正
更新2019-5-19
:更新排版,增加内容参考资料:
一点HTTP知识
GET(1)
GET
方式传输数据时,数据附在URL
之后,即把数据放在HTTP
报文的报头。以?
分割URL
和传输数据,参数之间以&
相连。此后只讨论传输数据(即queryString
)的编码情况。空格会被转换成+
或%20
。如果数据是 ASCII码范围 的 非URL保留字 或 安全字符,保留数据。否则直接把字符串转换为percent-encoded bytes
,得出如:%E4%BD%A0%E5%A5%BD
,其中%XX
中的XX
为该符号 以16进制表示的字符编码,但所用字符集在不同情况下可能不同。(此处无了解URL
的编码方式的需求,故不做整理(懒),放出相关链接,有兴趣可以查看。或许以后会做整理。另请注意:queryString 的编码情况与 URL整体 (或 path路径)编码情况有所区别,比如对保留字符的处理)
【详解Javascript中的Url编码/解码】【js对url进行编码和解码(三种方式区别)】【JS中URL编码的问题】【Query string wiki】【Percent-encoding wiki】
GET
方式传输数据时并无数据大小限制。URL
不存在参数上限的问题,HTTP
协议规范没有对URL
长度进行限制。只有特定浏览器和服务器存在限制。
GET
传输数组时可按如下格式:a=1&a=2&a=3
,后台自动解析后会成为数组。只支持一维,多维数组需要自定义解析。
POST(1)
POST
方式传输数据时将数据放在HTTP
报文的正文中,存在多种数据格式。
理论上讲,POST
是没有大小限制的,HTTP
协议规范也没有进行大小限制。起限制作用的是服务器的处理程序的处理能力。
常见POST数据格式(2)
application/x-www-form-urlencoded
报文中用
name1=value1&name2=value2...
格式写入数据。数组传输与GET
一致
multipart/form-data
报文中有
boundary
分隔字符(自动生成),将每个input
中的数据分隔开来。需要在input
中注明name
属性,服务器才可获取,每个单元中有说明数据格式,默认为text/plain
。后端自动解析为key-value
,value
均为字符串。若有重复的name
,会自动解析生成数组,不会导致数据被覆盖,与GET
实际上类似。可用来上传文件,body
中会包含文件的MIME
格式(Content-Type
)。
text/plain
application/json
可以包含复杂的数据类型
前端中发送方式
form
GET
form
默认为GET
方法提交。action
为提交网址。
POST
只要设置form
中的method
属性为post
即可。
<form>
的enctype
属性设置数据格式。有:application/x-www-form-urlencoded
,multipart/form-data
,text/plain
(HTML5)。默认为application/x-www-form-urlencoded
。而当上传文件时,只能用multipart/form-data
。上传多个文件时需设置<input>
的multiple
属性。
更多详细请前往MDN
缺点:浏览器会有转跳。
注:method
和enctype
可能被覆盖。见此处
再注:无法传送application/json
类型数据。
fetch
fetch
可以实现多种提交方式和数据类型,此处为POST
提交JSON
数据。JSON
数据可由JSON.stringify
从指定对象中生成。fetch
详细见此处1
2
3
4
5
6
7
8
9
10
11
12fetch('/submit',{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
a:{
b:[1,2,3]
},
c:[[1,[2]],3]
})
})
fetch
获取服务器返回数据(详细见此处)1
2
3
4
5fetch(...)
.then(res=>{res.json())
.then(data=>{
...
})
注:XMLHttpRequest
与fetch
相似,若不追求兼容性,更推荐fetch
。fetch
也能实现ajax
,但现在渲染主要交给前端,服务器仅返回数据,返回内容通常为JSON
。
后台接收(Node.js)
(已引入模块:express
)
GET
只需使用req.query
即可获得解析后生成的对象1
2
3
4app.get('/submit',(req,res)=>{
console.log(req.query)
res.redirect(303,'/') // 转跳
})
POST
数据
text/plain
可以直接接收。代码如下:1
2
3
4
5
6
7
8let arr=[], chunks, data
req.on('data', buff => {
arr.push(buff);
});
req.on('end', () => {
chunks = Buffer.concat(arr);
data = chunks.toString();
});
application/x-www-form-urlencoded
和application/json
需要使用body-parser中间件解析数据。参数详解看这里(可能与新版本有出入,以github上为准)
在路由之前添加中间件1
2
3
4// for parsing application/json
app.use(bodyParser.json())
// for parsing application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }))
然后即可用req.body
获取解析后生成的对象,两种数据类型生成的对象无差别。1
2
3app.post('/submit',(req,res)=>{
console.log(req.body)
})
注:body-parser
不支持multipart/form-data
,此类型在下方提到
文件
若不使用express
则可以用res.on('data',chunk =>{...})
,但此方法需要考虑很多因素,需要额外的代码来使其更为健壮,在此不予讨论。有需要可以参考这篇文章或这篇文章
我选择引入Formidable模块1
2
3
4
5
6
7
8
9
10
11
12app.post('/submit', (req, res)=>{
const form = new formidable.IncomingForm()
form.multiples = true
form.parse(req, (err, fields, files)=>{
if(err) return res.redirect(303, '/error')
console.log('获取到的数据:')
console.log(fields)
console.log('获取到的文件:')
console.log(files)
});
res.redirect(303, '/')
})
其中form.multiples = true
可以在input
设置了multiple
后上传多个文件时生成数组。默认为false
,此时只能获取一个文件的信息。
multipart/form-data
中数据也可以此模块获取(也可以使用其他包,比如multiparty)
注:更多设置请查找Formidable
测试工具
唯一指定postman