Đăng yêu cầu x-www-form-urlencoded từ React Native


104

Tôi có một số tham số mà tôi muốn ĐĂNG biểu mẫu được mã hóa lên máy chủ của mình:

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

Tôi đang gửi yêu cầu của mình (hiện không có tham số) như thế này

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

Làm cách nào để đưa các tham số được mã hóa biểu mẫu vào yêu cầu?


2
Vui lòng cập nhật câu trả lời đã chọn của bạn thành câu trả lời đúng thực tế.
Albert Renshaw

Câu trả lời:


-49

Để tải lên các yêu cầu POST được mã hóa biểu mẫu, tôi khuyên bạn nên sử dụng đối tượng FormData .

Mã ví dụ:

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

79
Đây không phải là application / x-www-form-urlencoded, nhưng multipart / form-data
Haha TTpro

Tôi đồng tình, yêu cầu này sẽ không có "application / x-www-form-urlencoded" dưới dạng Content-Type mà là "multiart / form-data".
b4stien

2
@Mzn - Ví dụ: nếu bạn đang sử dụng một dịch vụ như API trình biên dịch đóng cửa của Google , máy chủ sẽ chỉ chấp nhận application/x-www-form-urlencodedchứ không phải multipart/form-data.
Sphinxxx

12
Làm thế nào đây có thể là câu trả lời được chấp nhận? Đó là sai lầm đơn giản liên quan đến câu hỏi thực tế ...
Żabojad

1
Bạn sẽ phải xử lý thêm trên máy chủ, khi gửi các đối tượng FormData. Về cơ bản xử lý một biểu mẫu thông thường như thể nó là một tệp tải lên. Ưu điểm của đối tượng FormData đối với biểu mẫu thông thường là gì?
MarsAndBack

251

Bạn phải tự mình tập hợp trọng tải x-www-form-urlencoded, như sau:

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

Lưu ý rằng nếu bạn đang sử dụng fetchtrong một trình duyệt (đủ hiện đại), thay vì React Native, thay vào đó bạn có thể tạo một URLSearchParamsđối tượng và sử dụng đối tượng đó làm phần thân, vì Tiêu chuẩn Tìm nạp nói rằng nếu đối tượng bodylà một URLSearchParamsđối tượng thì nó phải được tuần tự hóa thành application/x-www-form-urlencoded. Tuy nhiên, bạn không thể làm điều này trong React Native vì React Native không triển khaiURLSearchParams .


50
Cách ES6:const formBody = Object.keys(details).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(details[key])).join('&');
Eric Burel

Polyfill này cho URLSearchParams github.com/WebReflection/url-search-params có thể hoạt động cho React Native hoặc các trình duyệt cũ hơn.
bucabay

7
Một cách tương tự khác:const formBody = Object.entries(details).map(([key, value]) => encodeURIComponent(key) + '=' + encodeURIComponent(value)).join('&')
Flynn Hou

1
Nó chuyển đổi tham số mảng json thành chuỗi
atulkhatri


47

Sử dụng 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');

điều này làm cho những gì tôi dự định, vì php7 không phân tích cú pháp mã hóa FormData đúng. Tôi hy vọng nó được nhiều phiếu bầu cho các chàng trai và cô gái của PHP
cav_dan

6
-1; URLSearchParamskhông tồn tại trong React Native. (Xem github.com/facebook/react-native/issues/9596. )
Mark Amery

3
Nó là một phần của React Native bây giờ. Đảm bảo gọi toString()dữ liệu trước khi chuyển yêu cầu body.
phatmann 8/1018

Ngay cả sau khi RN nói rằng họ đã triển khai URLSearchParams, tôi vẫn gặp vấn đề. Tôi không nghĩ rằng nó được triển khai theo đúng thông số kỹ thuật và nó không chỉ là một giải pháp giảm. Vui lòng xem xét việc đọc URLSearchParams 'Lỗi: không được triển khai' nếu bạn cố gắng đăng nhập URLSearchParamsvà vẫn gặp sự cố.
0298

14

Vừa mới làm điều này và UrlSearchParams đã thực hiện thủ thuật Đây là mã của tôi nếu nó giúp được ai đó

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

Sau khi sử dụng npm, tôi truy vấn chuỗi - lưu nó hoạt động tốt.


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

nó rất hữu ích cho tôi và hoạt động mà không có bất kỳ lỗi nào

refrence: https://gist.github.com/milon87/f391e54e64e32e1626235d4dc4d16dc8


3

Chỉ dùng

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
Điều này nên được đánh dấu là câu trả lời chính xác nó. Nó rất dễ sử dụng và không có thứ gì kỳ lạ để chế tạo.
Augusto Gonzalez

1

Trong ví dụ ban đầu, bạn có một transformRequesthàm chuyển đổi một đối tượng thành dữ liệu Mã hóa Biểu mẫu.

Trong ví dụ đã sửa đổi, bạn đã thay thế nó JSON.stringifyđể chuyển đổi một đối tượng thành JSON.

Trong cả hai trường hợp, bạn đều có, 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'vì vậy bạn đang yêu cầu gửi dữ liệu được Mã hóa Biểu mẫu trong cả hai trường hợp.

Sử dụng chức năng Mã hóa biểu mẫu của bạn thay vì JSON.stringify.


Nâng cấp lại:

Trong fetchví dụ đầu tiên của bạn , bạn đặt bodylà giá trị JSON.

Bây giờ bạn đã tạo một phiên bản Mã hóa Biểu mẫu, nhưng thay vì đặt bodylà giá trị đó, bạn đã tạo một đối tượng mới và đặt dữ liệu Mã hóa Biểu mẫu làm thuộc tính của đối tượng đó.

Đừng tạo thêm đối tượng đó. Chỉ cần gán giá trị của bạn cho body.


Chào bạn @Quentin. Tôi vừa rút gọn hoàn toàn câu hỏi để thử và biến nó thành một tài liệu tham khảo hữu ích hơn cho những độc giả trong tương lai; khi làm như vậy, tôi đã hoàn toàn vô hiệu câu trả lời của bạn đề cập đến các chi tiết và lỗi của mã gốc của người hỏi. Tôi cho rằng bạn có quyền hoàn nguyên bản chỉnh sửa của tôi nếu bạn muốn - về lý thuyết, chúng tôi không có ý định thực hiện các chỉnh sửa làm mất hiệu lực câu trả lời, đó là điều tôi đã làm - nhưng nếu bạn sẵn lòng, tôi nghĩ vậy tốt hơn là chỉ nên xóa câu trả lời này thay thế; IMO câu hỏi đẹp hơn nhiều nếu không có mã Angular hoặc lần thử thất bại trước đó.
Mark Amery

1

Nếu bạn đang sử dụng JQuery, điều này cũng hoạt động ..

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

1

Không cần sử dụng jQuery querystringhoặc tập hợp trọng tải theo cách thủ công. URLSearchParamslà một cách để thực hiện và đây là một trong những câu trả lời ngắn gọn nhất với đầy đủ ví dụ về yêu cầu:

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

Có, bạn có thể sử dụng Axios hoặc bất cứ thứ gì bạn muốn thay thế fetch.

PS URLSearchParamskhông được hỗ trợ trong IE.


0

Theo thông số kỹ thuật , việc sử dụng encodeURIComponentsẽ không cung cấp cho bạn một chuỗi truy vấn phù hợp. Nó nói:

  1. Tên và giá trị điều khiển bị thoát. Các ký tự+ khoảng trắng được thay thế bằng , và sau đó các ký tự dành riêng được thoát ra như mô tả trong [RFC1738], phần 2.2: Các ký tự không phải chữ và số được thay thế bằng %HH, một dấu phần trăm và hai chữ số thập lục phân đại diện cho mã ASCII của ký tự. Ngắt dòng được biểu diễn dưới dạng cặp "CR LF" (tức là %0D%0A).
  2. Tên / giá trị điều khiển được liệt kê theo thứ tự xuất hiện trong tài liệu. Tên được ngăn cách với giá trị bằng =và các cặp tên / giá trị được phân tách với nhau bằng &.

Vấn đề là, encodeURIComponentmã hóa không gian để được %20, không +.

Phần thân của biểu mẫu phải được mã hóa bằng cách sử dụng một biến thể của các encodeURIComponentphương pháp được hiển thị trong các câu trả lời khác.

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

Bạn có thể sử dụng ứng dụng react-native-easy- dễ dàng hơn để gửi yêu cầu http và xây dựng yêu cầu chặn.

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);
    }
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.