199

我有一些参数要以表单编码形式发布到我的服务器:

{
    'userName': 'test@gmail.com',
    'password': 'Password!',
    'grant_type': 'password'
}

我正在像这样发送我的请求(目前没有参数)

var obj = {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
  },
};
fetch('https://example.com/login', obj)
  .then(function(res) {
    // Do stuff with result
  }); 

如何在请求中包含表单编码参数?

4

16 回答 16

377

您必须自己组合 x-www-form-urlencoded 有效负载,如下所示:

var details = {
    'userName': 'test@gmail.com',
    'password': 'Password!',
    'grant_type': 'password'
};

var formBody = [];
for (var property in details) {
  var encodedKey = encodeURIComponent(property);
  var encodedValue = encodeURIComponent(details[property]);
  formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");

fetch('https://example.com/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
  },
  body: formBody
})

请注意,如果fetch在(足够现代的)浏览器中使用,而不是 React Native,您可以创建一个URLSearchParams对象并将其用作主体,因为Fetch 标准规定如果它body是一个URLSearchParams对象,那么它应该被序列化为application/x-www-form-urlencoded. 但是,你不能在 React Native 中这样做,因为 React Native没有实现URLSearchParams.

于 2016-06-01T08:02:01.867 回答
257

更简单:

fetch('https://example.com/login', {
    method: 'POST',
    body: new URLSearchParams({
        'userName': 'test@gmail.com',
        'password': 'Password!',
        'grant_type': 'password'
    })
});

文档:https ://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch

于 2018-11-07T12:20:55.497 回答
62

利用URLSearchParams

https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams

var data = new URLSearchParams();
data.append('userName', 'test@gmail.com');
data.append('password', 'Password');
data.append('grant_type', 'password');
于 2017-07-27T17:25:14.360 回答
20

刚刚做到了,UrlSearchParams 成功了 如果它对某人有帮助,这是我的代码

import 'url-search-params-polyfill';
const userLogsInOptions = (username, password) => {



// const formData = new FormData();
  const formData = new URLSearchParams();
  formData.append('grant_type', 'password');
  formData.append('client_id', 'entrance-app');
  formData.append('username', username);
  formData.append('password', password);
  return (
    {
      method: 'POST',
      headers: {
        // "Content-Type": "application/json; charset=utf-8",
        "Content-Type": "application/x-www-form-urlencoded",
    },
      body: formData.toString(),
    json: true,
  }
  );
};


const getUserUnlockToken = async (username, password) => {
  const userLoginUri = `${scheme}://${host}/auth/realms/${realm}/protocol/openid-connect/token`;
  const response = await fetch(
    userLoginUri,
    userLogsInOptions(username, password),
  );
  const responseJson = await response.json();
  console.log('acces_token ', responseJson.access_token);
  if (responseJson.error) {
    console.error('error ', responseJson.error);
  }
  console.log('json ', responseJson);
  return responseJson.access_token;
};
于 2018-10-12T13:35:13.690 回答
17

无需使用 jQuery,querystring也无需手动组装有效负载。URLSearchParams是一种方法,这是完整请求示例中最简洁的答案之一:

fetch('https://example.com/login', {
  method: 'POST',
  body: new URLSearchParams({
    param: 'Some value',
    anotherParam: 'Another value'
  })
})
  .then(response => {
    // Do stuff with the response
  });

使用async/的相同技术await

const login = async () => {
  const response = await fetch('https://example.com/login', {
    method: 'POST',
    body: new URLSearchParams({
      param: 'Some value',
      anotherParam: 'Another value'
    })
  })

  // Do stuff with the response
}

是的,您可以使用 Axios 或任何其他 HTTP 客户端库来代替 native fetch

于 2020-08-20T09:08:12.957 回答
9
var details = {
    'userName': 'test@gmail.com',
    'password': 'Password!',
    'grant_type': 'password'
};

var formBody = [];
for (var property in details) {
  var encodedKey = encodeURIComponent(property);
  var encodedValue = encodeURIComponent(details[property]);
  formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");

fetch('http://identity.azurewebsites.net' + '/token', {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: formBody
})

它对我很有帮助,而且没有任何错误

参考:https ://gist.github.com/milon87/f391e54e64e32e1626235d4dc4d16dc8

于 2019-10-06T03:47:41.070 回答
8
*/ import this statement */
import qs from 'querystring'

fetch("*your url*", {
            method: 'POST',
            headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'},
            body: qs.stringify({ 
                username: "akshita",
                password: "123456",
            })
    }).then((response) => response.json())
      .then((responseData) => {
         alert(JSON.stringify(responseData))
    })

使用npm i querystring --save后它工作正常。

于 2019-05-02T05:18:55.927 回答
4

只需使用

import  qs from "qs";
 let data = {
        'profileId': this.props.screenProps[0],
        'accountId': this.props.screenProps[1],
        'accessToken': this.props.screenProps[2],
        'itemId': this.itemId
    };
    return axios.post(METHOD_WALL_GET, qs.stringify(data))
于 2018-07-02T20:15:31.810 回答
4

您可以使用FormDataURLSearchParams发布,application/x-www-form-urlencoded如下例所示:

如果您有表格:

<form>
    <input name="username" type="text" />
    <input name="password" type="password" />
    <button type="submit">login</button>
</form>

您可以添加使用下面的 JS 提交表单。

const form = document.querySelector("form");

form.addEventListener("submit", async () => {
    const formData = new FormData(form);
    try {
        await fetch("https://example.com/login", {
            method: "POST",
            headers: {
                "Content-Type": "application/x-www-form-urlencoded",
            },
            body: new URLSearchParams(formData),
        });
    } catch (err) {
        console.log(err);
    }
});
于 2021-11-12T10:16:29.880 回答
3

只需将 body 设置如下

var reqBody = "username="+username+"&password="+password+"&grant_type=password";

然后

fetch('url', {
      method: 'POST',
      headers: {
          //'Authorization': 'Bearer token',
          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
      },
      body: reqBody
  }).then((response) => response.json())
      .then((responseData) => {
          console.log(JSON.stringify(responseData));
      }).catch(err=>{console.log(err)})
于 2020-12-10T11:00:00.900 回答
2

如果您使用的是 JQuery,这也可以..

fetch(url, {
      method: 'POST', 
      body: $.param(data),
      headers:{
        'Content-Type': 'application/x-www-form-urlencoded'
      }
})
于 2018-07-19T22:05:22.220 回答
2

根据规范, usingencodeURIComponent不会为您提供符合要求的查询字符串。它指出:

  1. 控件名称和值被转义。空格字符被替换为+,然后保留字符被转义,如 [RFC1738] 第 2.2 节所述:非字母数字字符被替换为%HH、一个百分号和两个表示字符 ASCII 代码的十六进制数字。换行符表示为“CR LF”对(即%0D%0A)。
  2. 控件名称/值按照它们在文档中出现的顺序列出。名称与值之间由 分隔=,名称/值对之间由 分隔&

问题是,encodeURIComponent将空间编码为%20,而不是+

encodeURIComponent应使用其他答案中显示的方法的变体对表单主体进行编码。

const formUrlEncode = str => {
  return str.replace(/[^\d\w]/g, char => {
    return char === " " 
      ? "+" 
      : encodeURIComponent(char);
  })
}

const data = {foo: "bar߃©˙∑  baz", boom: "pow"};

const dataPairs = Object.keys(data).map( key => {
  const val = data[key];
  return (formUrlEncode(key) + "=" + formUrlEncode(val));
}).join("&");

// dataPairs is "foo=bar%C3%9F%C6%92%C2%A9%CB%99%E2%88%91++baz&boom=pow"
于 2018-09-06T13:58:38.647 回答
2

你可以使用react-native-easy-app更容易发送 http 请求和制定拦截请求。

import { XHttp } from 'react-native-easy-app';

* Synchronous request
const params = {name:'rufeng',age:20}
const response = await XHttp().url(url).param(params).formEncoded().execute('GET');
const {success, json, message, status} = response;


* Asynchronous requests
XHttp().url(url).param(params).formEncoded().get((success, json, message, status)=>{
    if (success){
       this.setState({content: JSON.stringify(json)});
    } else {
       showToast(msg);
    }
});
于 2020-04-01T06:15:43.020 回答
1

在原始示例中,您有一个transformRequest将对象转换为表单编码数据的函数。

在修改后的示例中,您已替换为JSON.stringify将对象转换为 JSON 的示例。

在这两种情况下'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',您都声称在这两种情况下都发送表单编码数据。

使用您的表单编码函数而不是JSON.stringify.


重新更新:

在您的第一个fetch示例中,您将 设置body为 JSON 值。

现在您已经创建了一个表单编码版本,但是您没有将 设置body为该值,而是创建了一个新对象并将表单编码数据设置为该对象的属性。

不要创建那个额外的对象。只需将您的值分配给body.

于 2016-02-13T21:55:01.783 回答
1

包裹fetch在一个简单的函数中

async function post_www_url_encdoded(url, data) {
    const body = new URLSearchParams();
    for (let key in data) {
        body.append(key, data[key]);
    }
    return await fetch(url, { method: "POST", body });
}

const response = await post_www_url_encdoded("https://example.com/login", {
    "name":"ali",
    "password": "1234"});
if (response.ok){ console.log("posted!"); }

于 2021-07-03T03:27:35.283 回答
-68

对于上传表单编码的 POST 请求,我建议使用FormData对象。

示例代码:

var params = {
    userName: 'test@gmail.com',
    password: 'Password!',
    grant_type: 'password'
};

var formData = new FormData();

for (var k in params) {
    formData.append(k, params[k]);
}

var request = {
    method: 'POST',
    headers: headers,
    body: formData
};

fetch(url, request);
于 2016-02-15T22:50:58.487 回答