Senden Sie POST-Daten mit XMLHttpRequest

526

Ich möchte einige Daten mit einem XMLHttpRequest in JavaScript senden.

Angenommen, ich habe das folgende Formular in 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>

Wie kann ich das Äquivalent mit einem XMLHttpRequest in JavaScript schreiben?

Jack Greenhill
quelle

Antworten:

748

Der folgende Code zeigt, wie das geht.

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);
Ed Heal
quelle
46
Ist es möglich, ein Objekt paramsanstelle einer Zeichenfolge wie in jQuery einzusenden ?
Vadorequest
4
Nein, aber in @ Vadorequests Kommentar wurde jQuery erwähnt - er fragte, ob es möglich sei, Daten "wie jQuery" zu übergeben. Ich erwähnte, wie ich denke, dass jQuery das macht und wie Sie dies erreichen können.
Dan Pantry
11
@EdHeal Connectionund Content-LengthHeader können nicht gesetzt werden. Es wird "Weigert sich, den unsicheren Header auf" Inhaltslänge "zu setzen" angezeigt. Siehe stackoverflow.com/a/2624167/632951
Pacerier
76
Hinweis: setRequestHeader () nach open (). Ich habe eine Stunde gebraucht, hoffe, dieser Kommentar spart jemandem eine Stunde;)
Kevin
4
ist es möglich eine application/jsonAnfrage zu senden ?
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');

Wenn Sie sich auf die Browserunterstützung verlassen können, können Sie FormData verwenden :

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);
uKolka
quelle
4
FormData verwendet das Formularelement als Konstruktorargument, ohne dass Werte einzeln hinzugefügt werden müssen
Juan Mendes
6
Ja, aber die Frage war, JavaScript-Äquivalent zum bereitgestellten Formular zu schreiben und das Formular nicht mit JavaScript zu senden.
Großbritannien Kolka
3
Die Antwort, die nur wenige Stimmen hat, aber als richtig markiert wurde, verwendet zwei zusätzliche Überschriften: http.setRequestHeader("Content-length", params.length);und http.setRequestHeader("Connection", "close");. Werden sie gebraucht? Werden sie vielleicht nur in bestimmten Browsern benötigt? (Es gibt einen Kommentar auf dieser anderen Seite, der besagt, dass das Setzen des Content-Length-Headers "genau das war, was benötigt wurde")
Darren Cook
@Darren Cook Implementierung abhängig. Nach meiner Erfahrung stellen die gängigen Browser die Inhaltslänge (erforderlich) automatisch aus den von Ihnen angegebenen Daten ein. Der Header "Verbindung" ist in den meisten Fällen standardmäßig "Keep-Alive", wodurch die Verbindung für eine Weile offen bleibt, sodass nachfolgende Anforderungen die Verbindung nicht erneut herstellen müssen, wie im Fall von "Schließen". Sie können diese Snippets in der Konsole unter Verwendung der aktuellen Seiten-URL testen und die Anforderungsheader mithilfe der Browser-Tools oder des Wiresharks überprüfen .
Großbritannien Kolka
4
@uKolka sollte in der Antwort vermerkt werden, dass sich bei Ihrer zweiten Lösung die Anfrage Content-Typeautomatisch ändert multipart/form-data. Dies hat schwerwiegende Auswirkungen auf die Serverseite und darauf, wie auf die Informationen dort zugegriffen wird.
AxeEffect
84

Verwenden Sie modernes JavaScript!

Ich würde vorschlagen, nachzuschauen fetch. Es ist das ES5-Äquivalent und verwendet Versprechen. Es ist viel besser lesbar und leicht anpassbar.

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

In Node.js müssen Sie Folgendes importieren fetch:

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

Wenn Sie es synchron verwenden möchten (funktioniert nicht im oberen Bereich):

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

Mehr Info:

Mozilla-Dokumentation

Kann ich verwenden (95% März 2020)

David Walsh Tutorial

Gibolt
quelle
4
Sie sollten die Verwendung von Versprechungen und fetten Pfeilen für Dinge vermeiden, die für die Funktionalität von Webseiten von entscheidender Bedeutung sind, da viele Geräte keine Browser haben, die diese Funktionen unterstützen.
Dmitry
8
Versprechen sind zu 90% gedeckt. Ich habe function()Beispiele hinzugefügt, falls Sie es nicht bevorzugen =>. Sie sollten unbedingt modernes JS verwenden, um die Entwicklererfahrung zu vereinfachen. Sich um einen kleinen Prozentsatz der Leute zu
sorgen, die im Internet Explorer
4
Fetter Pfeil funktioniert auch nicht mit thisSchlüsselwort. Ich möchte das erwähnen, aber ich hasse auch heimlich Leute, die thisArchitektur und Vererbungsarchitektur anstelle von Funktionsfabriken verwenden. Vergib mir, ich bin Knoten.
agm1984
3
Ich vermeide auch thisdie Pest, und so sollte es auch jeder lesen this.
Gibolt
2
Wenn Sie sich Sorgen um die Kompatibilität machen ... Google es6 Transpiler ... stackoverflow.com/questions/40205547/… . Schreiben Sie es einfach. Stellen Sie es kompatibel bereit. +1 vermeiden this.
TamusJRoyce
35

Minimale Verwendung von FormData, um eine AJAX-Anfrage zu senden

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

Bemerkungen

  1. Dadurch wird die OP-Frage nicht vollständig beantwortet, da der Benutzer klicken muss, um die Anforderung zu senden. Dies kann jedoch für Personen nützlich sein, die nach einer solchen einfachen Lösung suchen.

  2. Dieses Beispiel ist sehr einfach und unterstützt die GETMethode nicht. Wenn Sie an anspruchsvolleren Beispielen interessiert sind, schauen Sie sich bitte die hervorragende MDN-Dokumentation an . Siehe auch ähnliche Antwort zu XMLHttpRequest zum Posten von HTML-Formularen .

  3. Einschränkung dieser Lösung: Wie von Justin Blank und Thomas Munk (siehe ihre Kommentare) hervorgehoben, FormDatawird sie von IE9 und niedriger und dem Standardbrowser unter Android 2.3 nicht unterstützt.

olibre
quelle
1
Das einzige daran ist, dass FormData meiner Meinung nach in IE 9 nicht verfügbar ist und daher für viele Leute ohne Polyfill nicht verwendet werden kann. developer.mozilla.org/en-US/docs/Web/API/FormData
Justin Blank
Vielen Dank an @ThomasMunk für Ihren Link :-) Wir sehen, dass FormDatadies von vielen Browsern außer IE9 und Android 2.3 (und OperaMini, aber letzteres ist nicht weit verbreitet) unterstützt wird. Prost ;-)
Olibre
2
Elegante Lösung, aber Sie sollten angeben, dass onsubmit="return submitForm(this);"der Benutzer ansonsten zur URL in der Anforderung umgeleitet wird.
Vic
Vielen Dank an @Vic für Ihren Beitrag, ich habe die Antwort aktualisiert. Prost ;-)
Olibre
1
Ich bin nicht so erfahren mit Webentwicklung. Ich habe herausgefunden, dass die POST-Anfrage tatsächlich gesendet wird, wenn Sie zurückkehren false. Bei trueRücksendung wird die ursprüngliche (unerwünschte) POST-Anfrage gesendet! Ihre Antwort ist richtig, entschuldigen Sie die Verwirrung.
Markus L
30

Hier ist eine Komplettlösung mit 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>

Stellen Sie sicher, dass Ihre Backend-API JSON analysieren kann.

Zum Beispiel in Express JS:

import bodyParser from 'body-parser'
app.use(bodyParser.json())
agm1984
quelle
1
Großartig, aber verwenden Sie nicht den Wert 'false' für den asynchronen Parameter in XMLHttpRequest.open - er ist veraltet und gibt eine Warnung aus
Johnnycardy
Sollten wir dort true setzen oder diesen Parameter einfach weglassen? Ich werde die Antwort aktualisieren, wenn Sie angeben können, welche vorzuziehen ist.
agm1984
1
Es sollte standardmäßig true sein, aber ich weiß nicht, ob alle Browser dies respektieren
Johnnycardy
Angesichts der Standardeinstellung true werde ich es aus dem Beispiel entfernen und diese URL für Forschungszwecke
löschen
1
Ich mag das besser, weil es vernünftig ist und ein Detail weniger für jemanden am Anfang. Vielen Dank für die Hervorhebung.
agm1984
25

KEINE PLUGINS BENÖTIGT!

Wählen Sie den Code unten und ziehen Sie, dass in in der Lesezeichenleiste ( wenn Sie es nicht sehen, aktivieren Sie auf dem Browser - Einstellungen ), dann EDIT dass Link:

Geben Sie hier die Bildbeschreibung ein

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

Das ist alles! Jetzt können Sie jede Website besuchen und auf diese Schaltfläche in der BOOKMARK BAR klicken !


HINWEIS:

Die obige Methode sendet Daten mit der XMLHttpRequestMethode. Sie müssen sich also beim Auslösen des Skripts in derselben Domäne befinden. Deshalb sende ich lieber Daten mit einem simulierten FORMULAR, das den Code an jede Domain senden kann - hier ist der Code dafür:

 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); 
T.Todua
quelle
Kann ich für Mozilla etwas Ähnliches tun?
Ich habe nicht und ich konnte nicht: | Ich habe keine 125 Wiederholungen: | Und wenn Sie mein Profil sehen, werden Sie sehen, dass ich 136 Stimmen habe: | Selbst nachdem ich die Erlaubnis zum Downvote erhalten habe, werde ich es vermeiden, es sei denn, es ist notwendig: |
18
Und Ihre Frage beantwortet wirklich nicht, was OP verlangt hat. BookMarking einer HTTP-Anfrage ...!? Ich sehe keinen Punkt XmlHttpRequestin Ihrer Antwort: |
2
genial. Ich wollte nur eine Beziehung beim Überprüfen, da es eine Antwort war. Jetzt ist es eine Antwort plus ein Gr8-Tipp für alle, die vorbeischauen. Ich habe Stimmen zurückgesetzt. Prost
Iceman
5

Ich habe ein ähnliches Problem mit demselben Beitrag und diesem Link. Ich habe mein Problem behoben.

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

Dieser Link hat Informationen vervollständigt.

Laxman G.
quelle
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");
}
toto
quelle
1
Hallo Hugo, dieser Code dient zum Senden von Daten oder Dateien mit Fortschritts-Upload, wenn der Browser dies unterstützt. schloss alle möglichen Ereignisse und Kompatibilitätsbrowser ein. Es wird versucht, die neueste Objektklasse aus dem Browser zu verwenden. Es hilft dir?
Bis zum
2

Versuchen Sie, ein json-Objekt anstelle von Formulardaten zu verwenden. Unten ist der Code, der für mich funktioniert. formdata funktioniert auch bei mir nicht, daher habe ich diese Lösung gefunden.

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);
    }
}
Gehirnwäsche
quelle
1

Nur für Feature-Reader, die diese Frage finden. Ich habe festgestellt, dass die akzeptierte Antwort einwandfrei funktioniert, solange Sie einen bestimmten Pfad haben. Wenn Sie ihn jedoch leer lassen, schlägt er im IE fehl. Folgendes habe ich mir ausgedacht:

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

Du kannst es dir so gefallen:

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

Es gibt einige Duplikate, die dies berühren, und niemand erklärt es wirklich. Ich werde das akzeptierte Antwortbeispiel zur Veranschaulichung ausleihen

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

Ich habe dies http.onload(function() {})zur Veranschaulichung zu stark vereinfacht (ich verwende anstelle der älteren Methodik dieser Antwort). Wenn Sie dies so verwenden, wie es ist, werden Sie feststellen, dass Ihr Server den POST-Text wahrscheinlich als Zeichenfolge und nicht als tatsächliche key=valueParameter interpretiert (dh PHP zeigt keine $_POSTVariablen an). Sie müssen den Formular-Header übergeben, um das zu erhalten, und das vorher tunhttp.send()

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

Wenn Sie JSON und keine URL-codierten Daten verwenden, übergeben Sie application/jsonstattdessen

Machavity
quelle
1

Dies hat mir geholfen, da ich nur xmlHttpRequestein Objekt als Formulardaten verwenden und veröffentlichen wollte:

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

M3RS
quelle