Envoyer des données POST à ​​l'aide de XMLHttpRequest


526

Je voudrais envoyer des données en utilisant un XMLHttpRequest en JavaScript.

Disons que j'ai le formulaire suivant en HTML:

<form name="inputform" action="somewhere" method="post">
    <input type="hidden" value="person" name="user">
    <input type="hidden" value="password" name="pwd">
    <input type="hidden" value="place" name="organization">
    <input type="hidden" value="key" name="requiredkey">
</form>

Comment puis-je écrire l'équivalent à l'aide d'un XMLHttpRequest en JavaScript?

Réponses:


748

Le code ci-dessous montre comment procéder.

var http = new XMLHttpRequest();
var url = 'get_data.php';
var params = 'orem=ipsum&name=binny';
http.open('POST', url, true);

//Send the proper header information along with the request
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

http.onreadystatechange = function() {//Call a function when the state changes.
    if(http.readyState == 4 && http.status == 200) {
        alert(http.responseText);
    }
}
http.send(params);

46
Est-il possible d'envoyer un objet au paramslieu d'une chaîne comme dans jQuery?
Vadorequest

4
Non, mais le commentaire de @ Vadorequest mentionnait jQuery - il a demandé s'il était possible de transmettre des données "comme jQuery". J'ai mentionné comment je pense que jQuery le fait et donc, comment vous pourriez y parvenir.
Dan Pantry

11
@EdHeal Connectionet les en- Content-Lengthtêtes ne peuvent pas être définis. Il indiquera "Refus de définir un en-tête non sécurisé" content-length "". Voir stackoverflow.com/a/2624167/632951
Pacerier

76
Remarque: setRequestHeader () après open (). Cela m'a pris une heure, espérons que ce commentaire fera gagner une heure à quelqu'un;)
Kevin

4
est-il possible d'envoyer une application/jsondemande?

270
var xhr = new XMLHttpRequest();
xhr.open('POST', 'somewhere', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onload = function () {
    // do something to response
    console.log(this.responseText);
};
xhr.send('user=person&pwd=password&organization=place&requiredkey=key');

Ou si vous pouvez compter sur la prise en charge du navigateur, vous pouvez utiliser FormData :

var data = new FormData();
data.append('user', 'person');
data.append('pwd', 'password');
data.append('organization', 'place');
data.append('requiredkey', 'key');

var xhr = new XMLHttpRequest();
xhr.open('POST', 'somewhere', true);
xhr.onload = function () {
    // do something to response
    console.log(this.responseText);
};
xhr.send(data);

4
FormData prend l'élément de formulaire comme argument constructeur, pas besoin d'ajouter des valeurs individuellement
Juan Mendes

6
Oui, mais la question était d'écrire l'équivalent JavaScript du formulaire fourni et non de soumettre le formulaire en utilisant JavaScript.
uKolka

3
La réponse qui a peu de votes mais qui a été marquée comme correcte utilise deux en-têtes supplémentaires: http.setRequestHeader("Content-length", params.length);et http.setRequestHeader("Connection", "close");. Sont-ils nécessaires? Sont-ils seulement nécessaires sur certains navigateurs? (Il y a un commentaire sur cette autre page disant que définir l'en-tête Content-Length était "exactement ce qui était nécessaire")
Darren Cook

@Darren Cook Dépend de l'implémentation. D'après mon expérience, les principaux navigateurs définissent automatiquement la «longueur du contenu» (obligatoire) à partir des données que vous fournissez. Par défaut, l'en-tête «Connection» est «keep-alive», ce qui maintient la connexion ouverte pendant un certain temps afin que les requêtes suivantes n'aient pas à rétablir à nouveau la connexion comme dans le cas de «close». Vous pouvez essayer ces extraits dans la console, en utilisant l'URL de la page actuelle et inspecter les en-têtes de demande à l'aide des outils du navigateur ou de wirehark .
uKolka

4
@uKolka, il convient de noter sur la réponse qu'avec votre deuxième solution, la demande Content-Typechange automatiquement en multipart/form-data. Cela a de sérieuses implications côté serveur et comment les informations y sont accessibles.
AxeEffect

84

Utilisez du JavaScript moderne!

Je suggérerais d'examiner fetch. C'est l'équivalent ES5 et utilise Promises. Il est beaucoup plus lisible et facilement personnalisable.

const url = "http://example.com";
fetch(url, {
    method : "POST",
    body: new FormData(document.getElementById("inputform")),
    // -- or --
    // body : JSON.stringify({
        // user : document.getElementById('user').value,
        // ...
    // })
}).then(
    response => response.text() // .json(), etc.
    // same as function(response) {return response.text();}
).then(
    html => console.log(html)
);

Dans Node.js, vous devrez importer en fetchutilisant:

const fetch = require("node-fetch");

Si vous souhaitez l'utiliser de manière synchrone (ne fonctionne pas dans la portée supérieure):

const json = await fetch(url, optionalOptions)
  .then(response => response.json()) // .text(), etc.
  .catch((e) => {});

Plus d'informations:

Documentation de Mozilla

Puis-je utiliser (95% mars 2020)

Tutoriel de David Walsh


4
Vous devez éviter d'utiliser des promesses et des flèches grasses pour des choses aussi importantes pour la fonctionnalité des pages Web, car de nombreux appareils ne disposent pas de navigateurs prenant en charge ces fonctionnalités.
Dmitry du

8
Les promesses sont couvertes à 90%. J'ai ajouté des function()exemples au cas où vous ne préféreriez pas =>. Vous devez absolument utiliser JS moderne pour faciliter l'expérience du développeur. S'inquiéter d'un petit pourcentage de personnes bloquées sur IE n'en vaut la peine que si vous êtes une grande entreprise
Gibolt

4
La grosse flèche ne fonctionne pas non plus avec le thismot clé. J'aime le mentionner, mais je déteste aussi secrètement les gens qui utilisent thiset l'architecture d'héritage au lieu des usines fonctionnelles. Pardonnez-moi, je suis nœud.
agm1984

3
J'évite thisaussi la peste, et tout le monde devrait lire this.
Gibolt

2
Si vous vous inquiétez de la compatibilité ... Google es6 transpiler ... stackoverflow.com/questions/40205547/… . Écrivez-le simplement. Déployez-le compatible. +1 à éviter this.
TamusJRoyce

35

Utilisation minimale de FormDatapour soumettre une demande AJAX

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge, chrome=1"/>
<script>
"use strict";
function submitForm(oFormElement)
{
  var xhr = new XMLHttpRequest();
  xhr.onload = function(){ alert (xhr.responseText); } // success case
  xhr.onerror = function(){ alert (xhr.responseText); } // failure case
  xhr.open (oFormElement.method, oFormElement.action, true);
  xhr.send (new FormData (oFormElement));
  return false;
}
</script>
</head>

<body>
<form method="post" action="somewhere" onsubmit="return submitForm(this);">
  <input type="hidden" value="person"   name="user" />
  <input type="hidden" value="password" name="pwd" />
  <input type="hidden" value="place"    name="organization" />
  <input type="hidden" value="key"      name="requiredkey" />
  <input type="submit" value="post request"/>
</form>
</body>
</html>

Remarques

  1. Cela ne répond pas complètement à la question OP car cela oblige l'utilisateur à cliquer pour soumettre la demande. Mais cela peut être utile aux personnes qui recherchent ce type de solution simple.

  2. Cet exemple est très simple et ne prend pas en charge la GETméthode. Si vous êtes intéressé par des exemples plus sophistiqués, veuillez consulter l'excellente documentation MDN . Voir aussi une réponse similaire à propos de XMLHttpRequest pour publier un formulaire HTML .

  3. Limitation de cette solution: comme souligné par Justin Blank et Thomas Munk (voir leurs commentaires), FormDatan'est pas pris en charge par IE9 et inférieur, et le navigateur par défaut sur Android 2.3.


1
La seule chose à ce sujet est que je pense que FormData n'est pas disponible dans IE 9, donc il ne sera pas utilisable par beaucoup de gens sans polyfill. developer.mozilla.org/en-US/docs/Web/API/FormData
Justin Blank

Merci @ThomasMunk pour votre lien :-) Nous voyons que cela FormDataest supporté par de nombreux navigateurs sauf IE9 et Android 2.3 (et OperaMini mais ce dernier n'est pas largement utilisé). À la vôtre ;-)
olibre

2
Solution élégante, mais vous devez spécifier onsubmit="return submitForm(this);"sinon l'utilisateur est redirigé vers l'URL dans la demande.
Vic

Merci @Vic pour votre contribution, j'ai mis à jour la réponse.
Santé

1
Je ne suis pas très expérimenté en développement Web. J'ai compris que la demande POST est bien envoyée à votre retour false. Si trueest retourné, la demande POST d'origine (indésirable) sera envoyée! Votre réponse est correcte, désolé pour la confusion.
Markus L

30

Voici une solution complète avec application-json:

// Input values will be grabbed by ID
<input id="loginEmail" type="text" name="email" placeholder="Email">
<input id="loginPassword" type="password" name="password" placeholder="Password">

// return stops normal action and runs login()
<button onclick="return login()">Submit</button>

<script>
    function login() {
        // Form fields, see IDs above
        const params = {
            email: document.querySelector('#loginEmail').value,
            password: document.querySelector('#loginPassword').value
        }

        const http = new XMLHttpRequest()
        http.open('POST', '/login')
        http.setRequestHeader('Content-type', 'application/json')
        http.send(JSON.stringify(params)) // Make sure to stringify
        http.onload = function() {
            // Do whatever with response
            alert(http.responseText)
        }
    }
</script>

Assurez-vous que votre API backend peut analyser JSON.

Par exemple, dans Express JS:

import bodyParser from 'body-parser'
app.use(bodyParser.json())

1
Génial, mais n'utilisez pas la valeur "false" pour le paramètre async dans XMLHttpRequest.open - il est obsolète et donnera un avertissement
johnnycardy

Devrions-nous mettre vrai là ou simplement omettre ce paramètre? Je mettrai à jour la réponse si vous pouvez spécifier ce qui est préférable.
agm1984

1
La valeur par défaut devrait être true, mais je ne sais pas si tous les navigateurs respectent cela
johnnycardy

Étant donné la valeur par défaut true, je vais le supprimer de l'exemple et supprimer cette URL pour la recherche: developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open
agm1984

1
J'aime mieux parce que c'est raisonnable et un détail de moins pour quelqu'un pour commencer. Merci de l'avoir souligné.
agm1984

25

AUCUN PLUGIN NÉCESSAIRE!

Sélectionnez le code ci-dessous et faites-le glisser dans la BARRE DE SIGNETS ( si vous ne le voyez pas, activez-le dans les paramètres du navigateur ), puis MODIFIEZ ce lien:

entrez la description de l'image ici

javascript:var my_params = prompt("Enter your parameters", "var1=aaaa&var2=bbbbb"); var Target_LINK = prompt("Enter destination", location.href); function post(path, params) { var xForm = document.createElement("form"); xForm.setAttribute("method", "post"); xForm.setAttribute("action", path); for (var key in params) { if (params.hasOwnProperty(key)) { var hiddenField = document.createElement("input"); hiddenField.setAttribute("name", key); hiddenField.setAttribute("value", params[key]); xForm.appendChild(hiddenField); } } var xhr = new XMLHttpRequest(); xhr.onload = function () { alert(xhr.responseText); }; xhr.open(xForm.method, xForm.action, true); xhr.send(new FormData(xForm)); return false; } parsed_params = {}; my_params.split("&").forEach(function (item) { var s = item.split("="), k = s[0], v = s[1]; parsed_params[k] = v; }); post(Target_LINK, parsed_params); void(0);

C'est tout! Vous pouvez maintenant visiter n'importe quel site Web et cliquer sur ce bouton dans la BARRE DE SIGNETS !


REMARQUE:

La méthode ci-dessus envoie des données à l'aide de la XMLHttpRequestméthode, vous devez donc être sur le même domaine lors du déclenchement du script. C'est pourquoi je préfère envoyer des données avec une soumission de formulaire simulée, qui peut envoyer le code à n'importe quel domaine - voici le code pour cela:

 javascript:var my_params=prompt("Enter your parameters","var1=aaaa&var2=bbbbb"); var Target_LINK=prompt("Enter destination", location.href); function post(path, params) {   var xForm= document.createElement("form");   xForm.setAttribute("method", "post");   xForm.setAttribute("action", path); xForm.setAttribute("target", "_blank");   for(var key in params) {   if(params.hasOwnProperty(key)) {        var hiddenField = document.createElement("input");      hiddenField.setAttribute("name", key);      hiddenField.setAttribute("value", params[key]);         xForm.appendChild(hiddenField);     }   }   document.body.appendChild(xForm);  xForm.submit(); }   parsed_params={}; my_params.split("&").forEach(function(item) {var s = item.split("="), k=s[0], v=s[1]; parsed_params[k] = v;}); post(Target_LINK, parsed_params); void(0); 

Pour Mozilla, puis-je faire quelque chose de similaire à cela?

Je ne l'ai pas fait et je n'ai pas pu: | Je n'ai pas 125 représentants: | Et si vous voyez mon profil, vous verrez que j'ai 136 votes positifs: | Même après avoir obtenu la permission de voter, je l'éviterai à moins que ce ne soit nécessaire: |

18
Et votre question ne répond vraiment pas à ce que OP a demandé. BookMarking a HTTP Request ...!? Je ne vois aucun point relatif XmlHttpRequestdans votre réponse: |

2
impressionnant. Je voulais juste une relation en passant en revue car c'était une réponse. maintenant c'est une réponse plus une astuce gr8 pour tous ceux qui passent. j'ai rétabli les votes. cheers
Iceman

5

J'ai rencontré un problème similaire, en utilisant le même message et et ce lien, j'ai résolu mon problème.

 var http = new XMLHttpRequest();
 var url = "MY_URL.Com/login.aspx";
 var params = 'eid=' +userEmailId+'&amp;pwd='+userPwd

 http.open("POST", url, true);

 // Send the proper header information along with the request
 //http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
 //http.setRequestHeader("Content-Length", params.length);// all browser wont support Refused to set unsafe header "Content-Length"
 //http.setRequestHeader("Connection", "close");//Refused to set unsafe header "Connection"

 // Call a function when the state 
 http.onreadystatechange = function() {
    if(http.readyState == 4 && http.status == 200) {
        alert(http.responseText);
    }
 }
 http.send(params);

Ce lien a complété les informations.


4
var util = {
    getAttribute: function (dom, attr) {
        if (dom.getAttribute !== undefined) {
            return dom.getAttribute(attr);
        } else if (dom[attr] !== undefined) {
            return dom[attr];
        } else {
            return null;
        }
    },
    addEvent: function (obj, evtName, func) {
        //Primero revisar attributos si existe o no.
        if (obj.addEventListener) {
            obj.addEventListener(evtName, func, false);

        } else if (obj.attachEvent) {
            obj.attachEvent(evtName, func);
        } else {
            if (this.getAttribute("on" + evtName) !== undefined) {
                obj["on" + evtName] = func;
            } else {
                obj[evtName] = func;
            }

        }

    },
    removeEvent: function (obj, evtName, func) {
        if (obj.removeEventListener) {
            obj.removeEventListener(evtName, func, false);
        } else if (obj.detachEvent) {
            obj.detachEvent(evtName, func);
        } else {
            if (this.getAttribute("on" + evtName) !== undefined) {
                obj["on" + evtName] = null;
            } else {
                obj[evtName] = null;
            }
        }

    },
    getAjaxObject: function () {
        var xhttp = null;
        //XDomainRequest
        if ("XMLHttpRequest" in window) {
            xhttp = new XMLHttpRequest();
        } else {
            // code for IE6, IE5
            xhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        return xhttp;
    }

};

//START CODE HERE.

var xhr = util.getAjaxObject();

var isUpload = (xhr && ('upload' in xhr) && ('onprogress' in xhr.upload));

if (isUpload) {
    util.addEvent(xhr, "progress", xhrEvt.onProgress());
    util.addEvent(xhr, "loadstart", xhrEvt.onLoadStart);
    util.addEvent(xhr, "abort", xhrEvt.onAbort);
}

util.addEvent(xhr, "readystatechange", xhrEvt.ajaxOnReadyState);

var xhrEvt = {
    onProgress: function (e) {
        if (e.lengthComputable) {
            //Loaded bytes.
            var cLoaded = e.loaded;
        }
    },
    onLoadStart: function () {
    },
    onAbort: function () {
    },
    onReadyState: function () {
        var state = xhr.readyState;
        var httpStatus = xhr.status;

        if (state === 4 && httpStatus === 200) {
            //Completed success.
            var data = xhr.responseText;
        }

    }
};
//CONTINUE YOUR CODE HERE.
xhr.open('POST', 'mypage.php', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');


if ('FormData' in window) {
    var formData = new FormData();
    formData.append("user", "aaaaa");
    formData.append("pass", "bbbbb");

    xhr.send(formData);

} else {

    xhr.send("?user=aaaaa&pass=bbbbb");
}

1
Bonjour Hugo, Ce code est pour envoyer des données ou un fichier avec un téléchargement de progression si le navigateur le prend en charge. inclus tous les événements possibles et le navigateur de compatibilité. Il essaie d'utiliser la plus nouvelle classe d'objets du navigateur. Ça vous aide?
jusqu'au

2

Essayez d'utiliser l'objet json au lieu de formdata. ci-dessous est le code qui fonctionne pour moi. formdata ne fonctionne pas non plus pour moi, c'est pourquoi j'ai trouvé cette solution.

var jdata = new Object();
jdata.level = levelVal; // level is key and levelVal is value
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "http://MyURL", true);
xhttp.setRequestHeader('Content-Type', 'application/json');
xhttp.send(JSON.stringify(jdata));

xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      console.log(this.responseText);
    }
}

1

Juste pour les lecteurs de fonctionnalité qui trouvent cette question. J'ai trouvé que la réponse acceptée fonctionne bien tant que vous avez un chemin donné, mais si vous le laissez vide, il échouera dans IE. Voici ce que j'ai trouvé:

function post(path, data, callback) {
    "use strict";
    var request = new XMLHttpRequest();

    if (path === "") {
        path = "/";
    }
    request.open('POST', path, true);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    request.onload = function (d) {
        callback(d.currentTarget.response);
    };
    request.send(serialize(data));
}

Vous pouvez vous comme ça:

post("", {orem: ipsum, name: binny}, function (response) {
    console.log(respone);
})

1

Il y a des doublons qui touchent à cela, et personne ne l'explique vraiment. Je vais emprunter l'exemple de réponse accepté pour illustrer

http.open('POST', url, true);
http.send('lorem=ipsum&name=binny');

J'ai simplifié à l'extrême (j'utilise http.onload(function() {}) place de l'ancienne méthodologie de cette réponse) à des fins d'illustration. Si vous l'utilisez tel key=valuequel , vous constaterez que votre serveur interprète probablement le corps du POST comme une chaîne et non comme des paramètres réels (c'est-à-dire que PHP n'affichera aucune $_POSTvariable). Vous devez passer l'en-tête du formulaire pour l'obtenir et le faire avanthttp.send()

http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

Si vous utilisez JSON et non des données encodées URL, passez à la application/jsonplace


1

Cela m'a aidé car je voulais utiliser uniquement xmlHttpRequestet publier un objet en tant que données de formulaire:

function sendData(data) {
  var XHR = new XMLHttpRequest();
  var FD  = new FormData();

  // Push our data into our FormData object
  for(name in data) {
    FD.append(name, data[name]);
  }

  // Set up our request
  XHR.open('POST', 'https://example.com/cors.php');

  // Send our FormData object; HTTP headers are set automatically
  XHR.send(FD);
}

https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.