Invia dati POST utilizzando XMLHttpRequest


526

Vorrei inviare alcuni dati utilizzando XMLHttpRequest in JavaScript.

Supponiamo che io abbia il seguente modulo 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>

Come posso scrivere l'equivalente utilizzando un XMLHttpRequest in JavaScript?

Risposte:


748

Il codice seguente mostra come eseguire questa operazione.

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
È possibile inviare un oggetto paramsanziché una stringa come in jQuery?
Vadorequest,

4
No, ma il commento di @ Vadorequest menziona jQuery - ha chiesto se fosse possibile passare dati "come jQuery". Ho menzionato il modo in cui penso che jQuery lo faccia e, quindi, come si possa ottenere questo risultato.
Dan Pantry,

11
@EdHeal Connectione le Content-Lengthintestazioni non possono essere impostate. Dirà "Rifiutato di impostare l'intestazione non sicura" content-length "". Vedere stackoverflow.com/a/2624167/632951
Pacerier

76
Nota: setRequestHeader () dopo open (). Mi ci è voluto un'ora, speriamo che questo commento salvi qualcuno un'ora;)
Kevin,

4
è possibile inviare una application/jsonrichiesta?

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

Oppure, se puoi contare sul supporto del browser, puoi utilizzare 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 prende l'elemento del modulo come argomento del costruttore, non è necessario aggiungere valori singolarmente
Juan Mendes,

6
Sì, ma la domanda era scrivere l'equivalente JavaScript del modulo fornito non inviare il modulo utilizzando JavaScript.
uKolka,

3
La risposta che ha pochi voti ma che è stata contrassegnata come corretta utilizza due intestazioni aggiuntive: http.setRequestHeader("Content-length", params.length);e http.setRequestHeader("Connection", "close");. Sono necessari? Sono forse necessari solo su determinati browser? (C'è un commento su quell'altra pagina che dice che l'impostazione dell'intestazione Content-Length è "esattamente ciò che era necessario")
Darren Cook

@Darren Cook Implementazione dipendente. Dalla mia esperienza i principali browser impostate 'Content-length' (è necessario) automaticamente dai dati che fornite. Nella maggior parte dei casi, l'intestazione "Connessione" viene impostata automaticamente su "keep-alive", il che mantiene aperta la connessione per un po ', quindi le richieste successive non devono ristabilire nuovamente la connessione come nel caso di "chiudi". Puoi provare questi snippet nella console, utilizzando l'URL della pagina corrente e ispezionare le intestazioni delle richieste utilizzando gli strumenti del browser o il cablaggio .
uKolka,

4
@uKolka dovrebbe essere notato nella risposta che con la tua seconda soluzione la richiesta Content-Typecambia automaticamente multipart/form-data. Ciò ha serie implicazioni sul lato server e su come si accede alle informazioni lì.
AxeEffect,

84

Usa JavaScript moderno!

Suggerirei di esaminare fetch. È l'equivalente ES5 e utilizza le promesse. È molto più leggibile e facilmente personalizzabile.

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, dovrai importare fetchusando:

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

Se si desidera utilizzarlo in modo sincrono (non funziona nell'ambito principale):

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

Ulteriori informazioni:

Documentazione di Mozilla

Posso usare (95% marzo 2020)

David Walsh Tutorial


4
Dovresti evitare di usare Promises e fat frecce per cose così importanti per la funzionalità della pagina web, poiché molti dispositivi non dispongono di browser che supportano queste funzionalità.
Dmitry,

8
Le promesse sono coperte al 90%. Ho aggiunto degli function()esempi nel caso in cui non preferissi =>. Dovresti assolutamente utilizzare il moderno JS per facilitare l'esperienza degli sviluppatori. Preoccuparsi di una piccola percentuale di persone bloccate su IE non vale la pena a meno che tu non sia una grande impresa
Gibolt,

4
La freccia grassa inoltre non funziona con la thisparola chiave. Mi piace menzionarlo, ma odio anche segretamente le persone che usano thise l'architettura ereditaria invece delle fabbriche funzionali. Perdonami, sono un nodo.
agm1984,

3
Evito anche thisla peste, e così dovrebbe leggere chiunque this.
Gibolt,

2
Se preoccupati per la compatibilità ... Google ES6 transpiler ... stackoverflow.com/questions/40205547/... . Scrivi semplice. Distribuiscilo compatibile. +1 evita this.
TamusJRoyce,

35

Utilizzo minimo di FormDataper inviare una richiesta 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>

Osservazioni

  1. Questo non risponde completamente alla domanda OP perché richiede all'utente di fare clic per inviare la richiesta. Ma questo può essere utile per le persone che cercano questo tipo di soluzione semplice.

  2. Questo esempio è molto semplice e non supporta il GETmetodo. Se sei interessante con esempi più sofisticati, dai un'occhiata all'eccellente documentazione MDN . Vedi anche una risposta simile su XMLHttpRequest a Post HTML Form .

  3. Limitazione di questa soluzione: come sottolineato da Justin Blank e Thomas Munk (vedi i loro commenti), FormDatanon è supportato da IE9 e inferiori e browser predefinito su Android 2.3.


1
L'unica cosa a riguardo è che penso che FormData non sia disponibile in IE 9, quindi non sarà utilizzabile per molte persone senza un polyfill. developer.mozilla.org/en-US/docs/Web/API/FormData
Justin Blank

Grazie @ThomasMunk per il tuo link :-) Vediamo che FormDataè supportato da molti browser tranne IE9 e Android 2.3 (e OperaMini ma quest'ultimo non è ampiamente usato). Saluti ;-)
olibre

2
Soluzione elegante, ma è necessario specificare onsubmit="return submitForm(this);"altrimenti l'utente verrà reindirizzato all'URL nella richiesta.
Vic

Grazie @Vic per il tuo contributo, ho aggiornato la risposta. Saluti ;-)
olibre

1
Non ho esperienza con lo sviluppo web. Ho capito che la richiesta POST viene effettivamente inviata al tuo ritorno false. Se trueviene restituito, verrà inviata la richiesta POST originale (indesiderata)! La tua risposta è corretta, scusami per la confusione.
Markus L

30

Ecco una soluzione completa con 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>

Assicurarsi che l'API di back-end possa analizzare JSON.

Ad esempio, in Express JS:

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

1
Fantastico, ma non usare il valore "falso" per il parametro asincrono in XMLHttpRequest.open - è obsoleto e genererà un avviso
johnnycardy

Dovremmo mettere vero lì o semplicemente omettere quel parametro? Aggiornerò la risposta se è possibile specificare quale sia preferibile.
agm1984,

1
Dovrebbe essere
impostato

Dato il valore predefinito true, lo rimuoverò dall'esempio e rilascerò questo URL per la ricerca: developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open
agm1984,

1
Mi piace di più perché è ragionevole e un dettaglio in meno per qualcuno con cui iniziare. Grazie per averlo evidenziato.
agm1984,

25

NESSUN PLUGIN NECESSARIO!

Seleziona il codice seguente e trascinalo in BOOKMARK BAR ( se non lo vedi, abilita dalle Impostazioni del browser ), quindi MODIFICA quel link:

inserisci qui la descrizione dell'immagine

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

È tutto! Ora puoi visitare qualsiasi sito Web e fare clic sul pulsante in BOOKMARK BAR !


NOTA:

Il metodo precedente invia i dati utilizzando il XMLHttpRequestmetodo, quindi è necessario trovarsi nello stesso dominio durante l'attivazione dello script. Ecco perché preferisco inviare i dati con un MODULO DI PRESENTAZIONE simulato, che può inviare il codice a qualsiasi dominio - ecco il codice per questo:

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

Per Mozilla, posso fare qualcosa di simile a questo?

Non l'ho fatto e non ho potuto: | Non ho 125 ripetizioni: | E se vedi il mio profilo vedrai che ho 136 voti in su: | Anche dopo che avrò il permesso di sottovalutare, lo eviterò a meno che non sia necessario: |

18
E la tua domanda in realtà non risponde a ciò che OP ha richiesto. Segnalazione di una richiesta HTTP ...!? Non vedo alcun punto relativo XmlHttpRequestnella tua risposta: |

2
eccezionale. volevo solo qualche relazione durante la revisione poiché era una risposta. ora è una risposta più un suggerimento gr8 per tutti quelli che passano. ho annullato i voti. salute
Iceman,

5

Ho riscontrato un problema simile, usando lo stesso post e e questo link ho risolto il mio problema.

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

Questo link ha completato le informazioni.


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
Ciao Hugo, questo codice serve per inviare dati o file con upload progressivo se il browser lo supporta. incluso tutti i possibili eventi e browser di compatibilità. Prova a utilizzare la più nuova classe di oggetti dal browser. Ti aiuta?
toto

2

Prova a usare l'oggetto json invece di formdata. di seguito è riportato il codice che funziona per me. formdata non funziona neanche per me, quindi ho trovato questa soluzione.

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

Solo per i lettori di funzioni che trovano questa domanda. Ho scoperto che la risposta accettata funziona bene fintanto che hai un determinato percorso, ma se la lasci vuota, fallirà in IE. Ecco cosa mi è venuto in mente:

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

Puoi farlo così:

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

1

Ci sono alcuni duplicati che toccano questo, e nessuno lo spiega davvero. Prenderò in prestito l'esempio di risposta accettata per illustrare

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

L'ho semplificato troppo (io uso http.onload(function() {})invece della metodologia più vecchia di quella risposta) per motivi di illustrazione. Se usi questo così com'è, scoprirai che probabilmente il tuo server sta interpretando il corpo POST come una stringa e non come key=valueparametri reali (cioè PHP non mostrerà alcuna $_POSTvariabile). È necessario passare l'intestazione del modulo per ottenerlo e farlo primahttp.send()

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

Se stai utilizzando JSON e non dati con codifica URL, passa application/jsoninvece


1

Questo mi ha aiutato perché volevo usare solo xmlHttpRequeste pubblicare un oggetto come dati del modulo:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.