HTTP 的数据传输方式和编码格式

461 阅读3分钟

我们向后端发起 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 encodeURLComponentAPI 进行处理, 或者 query-stringqs 这两个 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。

image-20230525192242285

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

image-20230525205107048

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-TypeJSON.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

image-20230525212808051

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} />;
}