HTTP 的数据传输方式和编码格式
我们向后端发起 http 请求时,会要求指定数据传输的方式,通常情况下包含如下 5 种
- query
- url param
- form-urlencoded
- form-data
- json
下面我会讲述之间的区别,并同时列举 axios 和 fetch 的写法。
url param
这个是最简单的,一般用在 GET 请求中,就是直接在 url 后面加上参数,例如:
http://localhost:3000/post/7231564187255881765
这种一般用于请求某篇文章之类的。
axios
axios.get("http://localhost:3000/post/7231564187255881765")
fetch
fetch("http://localhost:3000/post/7231564187255881765")
query
这种也一般用在 GET 请求中,就是利用 &
来分割数据,例如:
http://localhost:3000/posts?page=1&size=10
一般 GET 请求需要传递多个参数都会用这种,比如上方例子中的分页请求。
这种请求如果涉及到中文或特殊字符需要进行编码才行,一般可以用 JavaScript encodeURLComponent
API 进行处理, 或者 query-string
或 qs
这两个 npm 库。
不过现在浏览器都比较智能了,已经会自动帮你进行特殊编码了,所以就算你不进行处理也没关系。
axios
axios 已经帮你做好编码处理了,你可以直接写。
axios.get("http://localhost:3000/user", {
params: {
name: "史蒂夫",
},
});
fetch
fetch 已经帮你做好编码处理了,但为了兼容性和可靠性,也可以显式地使用 encodeURIComponent
对 URL 的各个部分进行编码。
fetch(`http://localhost:3000/person/?name=${encodeURIComponent("史蒂夫")}`);
// 或者
fetch(`http://localhost:3000/person/?name=史蒂夫`);
form-urlencoded
这种也一般用在 POST 请求中,form 直接提交数据就是这种,它其实和 query 差不多,都是利用 &
来拼接数据,也都要进行编码,只不过 form-urlencoded
把这个字符串放在 body 里了,然后指定 Content-Type 是 application/x-www-form-urlencoded
,不过这种方式用的相对较少,大多数后端都会要求传 JSON。
axios
axios 会自动帮你把 Content-Type 指定为 application/x-www-form-urlencoded
,所以直接在 body 里放入数据即可
axios.post(`http://localhost:3000/user`, "id=123&name=suemor");
但这么写不太优雅,一般会配合 qs 这个库来使用
pnpm i qs
import qs from "qs";
axios.post(
`http://localhost:3000/user`,
qs.stringify({ id: 123, name: "suemor" })
);
fetch
注意 fetch 并没有帮你指定 Content-Type,需要手动指定为 application/x-www-form-urlencoded
import qs from "qs";
fetch(`http://localhost:3000/user`, {
method: "POST",
body: "id=123&name=suemor",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
// 或者
fetch(`http://localhost:3000/user`, {
method: "POST",
body: qs.stringify({ id: 123, name: "suemor" }),
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
json
这种也一般用在 POST 请求中,是我们 POST 请求最常见的一种传输方式,直接传递 JSON,且无需编码,需要指定 Content-Type 为 application/json
。
axios
axios 会自动帮你把 Content-Type 指定为 application/json
,且自动包了一层 JSON.stringify
,你只要在第二参数中传入 JavaScript 对象即可。
axios.post(`http://localhost:3000/user`, { id: 123, name: "suemor" });
// 等价于
axios.post(`http://localhost:3000/user`, `{"id":123,"name":"suemor"}`, {
headers: {
"Content-Type": "application/json",
},
});
fetch
fetch 就没 axios 那么智能了,需要手动指定Content-Type
和 JSON.stringify
fetch(`http://localhost:3000/user`, {
method: "POST",
body: JSON.stringify({ id: 123, name: "suemor" }),
headers: {
"Content-Type": "application/json",
},
});
form-data
这种也用在 POST 请求中,一般用于文件上传,--------- + 随机数
做为分隔符,无需编码,需要指定 Content-Type 为 multipart/form-data
。
axios
axios 会自动添加 Content-Type 为 multipart/form-data
function App() {
const upLoadHandler = (event: ChangeEvent<HTMLInputElement>) => {
const formData = new FormData();
const fileList = event.target.files;
if (!fileList) return;
formData.set("File", fileList[0]);
formData.set("id", "123");
axios.post(`http://localhost:3000/file`, formData);
};
return <input type="file" name="file" onChange={upLoadHandler} />;
}
fetch
fetch 会自动添加 Content-Type 为 multipart/form-data
,写法与 axios 类似
function App() {
const upLoadHandler = (event: ChangeEvent<HTMLInputElement>) => {
const formData = new FormData();
const fileList = event.target.files;
if (!fileList) return;
formData.set("File", fileList[0]);
formData.set("id", "123");
fetch(`http://localhost:3000/file`, {
method: "POST",
body: formData,
});
};
return <input type="file" name="file" onChange={upLoadHandler} />;
}