ReactNativeからx-www-form-urlencodedリクエストを投稿する


110

サーバーにフォームエンコードしたPOSTしたいパラメーターがいくつかあります。

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

フォームにエンコードされたパラメータをリクエストに含めるにはどうすればよいですか?


2
選択した回答を実際の正解に更新してください。
アルバートレンショー

回答:


-58

フォームでエンコードされた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);

85
これはapplication / x-www-form-urlencodedではなく、multipart / form-data
Haha TTpro 2016年

同意します。このリクエストには、Content-Typeとして「application / x-www-form-urlencoded」ではなく、「multipart / form-data」が含まれます。
b4stien 2016

2
@ Mzn-たとえば、GoogleのClosure Compiler APIなどのサービスを使用している場合、サーバーはを受け入れるだけで、を受け入れapplication/x-www-form-urlencodedませんmultipart/form-data
Sphinxxx 2017年

12
これはどのように受け入れられた答えになることができますか?これは、実際の質問...に関する平野間違っている
Żabojad

1
FormDataオブジェクトを送信するときは、サーバーで追加の処理を行う必要があります。基本的に、通常のフォームをファイルのアップロードであるかのように処理します。通常のフォームに対するFormDataオブジェクトの利点は何ですか?
MarsAndBack 2018

265

次のように、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(十分に現代)のブラウザではなく、ネイティブに反応して、あなたの代わりに作成することができURLSearchParamsているので、その体としてのオブジェクトと使用を標準状態取得あればということbodyであるURLSearchParams、オブジェクト、それのようにシリアル化する必要があるがapplication/x-www-form-urlencoded。ただし、React Nativeはを実装していないURLSearchParamsため、ReactNativeではこれを行うことはできません。


51
ES6の方法:const formBody = Object.keys(details).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(details[key])).join('&');
Eric Burel 2017

URLSearchParams github.com/WebReflection/url-search-paramsのこのポリフィルは、ReactNativeまたは古いブラウザーで機能する場合があります。
bucabay 2018

7
別の同様の方法:const formBody = Object.entries(details).map(([key, value]) => encodeURIComponent(key) + '=' + encodeURIComponent(value)).join('&')
Flynn Hou

1
json配列パラメーターを文字列に変換します
atulkhatri 2018年

私は提案されたすべての方法を試しました。私が何をしても、fetchは不要な引用符を本文の周りに直接文字列に挿入します-引用符の開始と終了。これにより、パラメータが解析されます。たとえば、次のようになります: '"mykey': 'myvalue"'。誰がこの問題を持っているこれらのコースだけで400エラー(サーバーがmykeyを、ない「にmykeyを認識する)の結果として、不可能なAPIを呼び出すになり不可解。?。
デイブ・マンガー


49

使用する 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');

php7はFormDataエンコーディングを正しく解析していなかったので、これは私が意図したものになります。PHPの男の子とギャルの投票が増えることを願っています
cav_dan 2017年

6
-1; URLSearchParamsReactNativeには存在しません。(github.com/facebook/react-native/issues/9596を参照してください
Mark Amery

3
現在、ReactNativeの一部です。toString()リクエストを渡す前に、必ずデータを呼び出してくださいbody
ファットマン2018年

RNが実装したと言った後でもURLSearchParams、私はまだ問題を抱えています。仕様どおりに実装されているとは思いませんし、単なるソリューションの低下ではありません。ドロップインしようとしても問題が発生する場合は、URLSearchParamsの「エラー:実装されていません」を読むことを検討してくださいURLSearchParams
zero2 9819

14

これを実行し、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;
};

5
*/ 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を使用した後、正常に動作します。


5
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


3

使用するだけ

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

1
これは正解としてマークする必要があります。それはとても使いやすく、作るための奇妙なものはありません。
オーガストゴンザレス

3

jQueryを使用しquerystringたり、ペイロードを手動でアセンブルしたりする必要はありません。URLSearchParamsは行く方法であり、これが完全なリクエストの例で最も簡潔な答えの1つです。

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

PSURLSearchParamsはIEではサポートされていません。


2

本体を次のように設定するだけです

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

1

元の例ではtransformRequest、オブジェクトをフォームエンコードされたデータに変換する関数があります。

改訂された例ではJSON.stringify、オブジェクトをJSONに変換するものに置き換えました。

どちらの場合も、フォームエンコードされたデータを送信'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'いると主張していることになります。

の代わりにフォームエンコーディング関数を使用してくださいJSON.stringify


再更新:

最初のfetch例では、をbodyJSON値に設定します。

これでフォームエンコードバージョンが作成されましたが、bodyをその値に設定する代わりに、新しいオブジェクトを作成し、フォームエンコードデータをそのオブジェクトのプロパティとして設定しました。

その余分なオブジェクトを作成しないでください。に値を割り当てるだけbodyです。


こんにちは@Quentin。将来の読者にとってより有用なリファレンスになるように、質問を根本的にスリム化しました。そうすることで、私はあなたの答えを完全に無効にしました。それは、質問者の元のコードの詳細とバグに言及しています。必要に応じて、編集を元に戻す権利があると思います-理論的には、私が行ったことである、回答を無効にする編集を行うことを意図していません-しかし、あなたが喜んでそうするのであれば、私はそれを考えます代わりに、この回答を削除する方がよいでしょう。IMOの質問は、Angularコードや以前の失敗した試行がなければ、はるかに優れています。
マークアメリー2017

1

JQueryを使用している場合、これも機能します。

fetch(url, {
      method: 'POST', 
      body: $.param(data),
      headers:{
        'Content-Type': 'application/x-www-form-urlencoded'
      }
})

0

仕様によると、を使用しencodeURIComponentても適合クエリ文字列は得られません。それは述べています:

  1. コントロールの名前と値はエスケープされます。[RFC1738]のセクション2.2で説明されているように、スペース文字はに置き換えられ+、予約文字はエスケープされます。英数字以外の文字は%HH、パーセント記号と、文字のASCIIコードを表す2つの16進数に置き換えられます。改行は「CRLF」ペア(つまり、%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"

0

httpリクエストの送信とインターセプトリクエストの作成が簡単なreact-native-easy-appを使用できます。

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);
    }
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.