Javascript 如何使用Fetch发布x-www-form-urlencoded请求?

Javascript 如何使用Fetch发布x-www-form-urlencoded请求?,javascript,http-post,fetch-api,Javascript,Http Post,Fetch Api,我有一些参数要发布到我的服务器上: { 'userName': 'test@gmail.com', 'password': 'Password!', 'grant_type': 'password' } 我发送的请求(目前没有参数)如下 var obj = { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', }

我有一些参数要发布到我的服务器上:

{
    '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
  }); 

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

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

在修订后的示例中,您将其替换为将对象转换为JSON的
JSON.stringify

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

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


重新更新:

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

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


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

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

示例代码:

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);

您必须自己组装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,则可以创建一个对象并将其用作主体,因为如果
body
URLSearchParams
对象,则应将其序列化为
application/x-www-form-urlcoded
。但是,您不能在React-Native中执行此操作,因为React-Native。

使用
URLSearchParams

只用

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))

如果您使用的是JQuery,那么它也可以工作

fetch(url, {
      method: 'POST', 
      body: $.param(data),
      headers:{
        'Content-Type': 'application/x-www-form-urlencoded'
      }
})
根据,使用
encodeURIComponent
不会给您提供一致的查询字符串。它说:

  • 控件名称和值被转义空格字符替换为
    +
    ,然后按照[RFC1738]第2.2节:非字母数字字符替换为
    %HH
    ,一个百分号和两个十六进制数字,表示字符的ASCII码。换行符表示为“CR LF”对(即,
    %0D%0A
  • 控件名称/值按它们在文档中的显示顺序列出。名称与值之间用
    =
    分隔,名称/值对之间用
    &
    分隔
  • 问题是,
    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"
    

    就这么做了,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;
    };
    
    更简单的是:

    fetch('https://example.com/login', {
    方法:“POST”,
    正文:新URLSearchParams({
    “用户名”:”test@gmail.com',
    “密码”:“密码!”,
    “授权类型”:“密码”
    })
    });
    
    文件:

    使用npm i querystring后——保存工作正常

    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
    })
    
    这对我很有帮助,而且没有任何错误

    参考:

    您可以使用更容易发送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);
        }
    });
    

    无需使用jQuery、
    querystring
    或手动组装负载
    URLSearchParams
    是一种方法,下面是一个最简洁的答案,包含完整的请求示例:

    fetch('https://example.com/login', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: new URLSearchParams({
        'param': 'Some value',
        'another_param': 'Another value'
      })
    })
      .then(res => {
        // Do stuff with the result
      });
    
    是的,您可以使用Axios或任何您想要的工具,而不是
    fetch


    注意:IE中不支持URLSearchParams。

    只需将主体设置为以下内容

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


    这不是application/x-www-form-urlencoded,而是multipart/form-dataI concure,此请求的内容类型不是“application/x-www-form-urlencoded”,而是“multipart/form-data”。@Mzn-例如,如果您使用的是像谷歌这样的服务,服务器将只接受
    application/x-www-form-urlencoded
    ,不是
    multipart/form data
    。这怎么可能是公认的答案?关于实际问题,这显然是错误的……在提交FormData对象时,您必须在服务器上进行额外的处理。基本上是像文件上传一样处理常规表单。对于常规表单,FormData对象的优势是什么?ES6方式:
    constFormBody=Object.keys(details).map(key=>encodeURIComponent(key)+'='+encodeURIComponent(details[key])。join('&')
    URLSearchParams的polyfill可能适用于React本机或旧版浏览器。另一种类似的方法:
    const formBody=Object.entries(details).map([key,value])=>encodeURIComponent(key)+'='+encodeURIComponent(value)).join('&')URLSearchParams
    在React-Native中不存在。(请参阅)它现在是React-Native的一部分。一定要调用
    toString()在传递请求之前的数据<代码>正文< /代码>。即使RN说他们执行了代码> URLSearchParams < /代码>,我仍然有问题。我不认为它是按照规范来实现的,它不仅仅是解决方案中的一个问题。如果您试图进入代码< URLSearchParams >,请考虑阅读。
    
    fetch('https://example.com/login', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: new URLSearchParams({
        'param': 'Some value',
        'another_param': 'Another value'
      })
    })
      .then(res => {
        // Do stuff with the result
      });
    
    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)})