使用 XMLHttpRequest 发送 POST 数据

我希望使用JavaScript中的XMLHttpRequest发送一些数据。 假设我有以下形式的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>

如何在JavaScript中使用XMLHttpRequest编写等效项?

转载于:https://stackoverflow.com/questions/9713058/send-post-data-using-xmlhttprequest

8个回答

The code below demonstrates on how to do this.

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);
weixin_41568127
?yb? You can use developer.mozilla.org/en-US/docs/Web/API/URLSearchParams to ease the management of query params.
大约 2 年之前 回复
csdnceshi65
larry*wei application/x-www-form-urlencoded tells the server to expect that the data submitted is url encoded. The values in the answer ("ipsum" and "binny") don't include any characters that require encoding, but if they did that can be accomplished using encodeURIComponent('value'). For example encodeURIComponent('this&that') would return this%26that. Otherwise the server would interpret the & as delimiting the next key=value pair.
2 年多之前 回复
csdnceshi79
python小菜 true argument in http.open method specifies synchronicity per w3school link. It'd better to write code like const async = true; http.open(..., async);
2 年多之前 回复
csdnceshi67
bug^君 And.... you need to JSON.stringify() the params or it will throw invalid JSON error in the Backend.
接近 3 年之前 回复
csdnceshi67
bug^君 I just tested and my Express API accepted application/json like a hot damn. The code in this above answer works if you paste it in and change the encoding type. Then, you can make params an object. Just make sure your API handles it. I am using bodyParser with JSON enabled.
接近 3 年之前 回复
csdnceshi68
local-host it's also noteworthy to mention the third param in setRequestHeader which expects a bool which determines if the request is cached or not...this could cause a serious headache if the result is cached as further requests would fail
大约 3 年之前 回复
csdnceshi51
旧行李 You should be able to set any custom content type, as long as your server knows how to interpret it.
3 年多之前 回复
csdnceshi76
斗士狗 is it possible to send an application/json request?
3 年多之前 回复
csdnceshi59
ℙℕℤℝ Note: setRequestHeader() after open(). Took me an hour, let's hope this comment saves someone an hour ;)
接近 4 年之前 回复
weixin_41568110
七度&光 Connection and Content-Length headers cannot be set. It'll say "Refused to set unsafe header "content-length"" . See stackoverflow.com/a/2624167/632951
大约 5 年之前 回复
csdnceshi74
7*4 No, but @Vadorequest's comment mentioned jQuery - he asked if it were possible to pass data "like jQuery". I mentioned how I think jQuery does it and thus, how you could achieve this.
5 年多之前 回复
csdnceshi64
游.程 - The question is not tagged jquery
5 年多之前 回复
csdnceshi74
7*4 Correct me if I'm wrong, but doesn't jquery just encode the object into a series of key-value pairs? You could always base64-encode the object although this may lead to unwieldy urls
5 年多之前 回复
csdnceshi70
笑故挽风 Is it possible to send an object in params instead of a string like in jQuery?
接近 6 年之前 回复
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');

Or if you can count on browser support you could use 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);
csdnceshi72
谁还没个明天 it should be noted on the reply than with your second solution the request Content-Type changes automatically to multipart/form-data. This has serious implications on the server side and how the information is accessed there.
大约 3 年之前 回复
csdnceshi70
笑故挽风 I think your comment should be a question. Doesn't seem like it has anything to do with XHR.
5 年多之前 回复
weixin_41568183
零零乙 I am using data = new FormData() and xhr.send(data);, but my method in the controller is never fired. What method parameters should I be using in the controller, I currently have [HttpPost] public async Task<ActionResult> Upload(HttpContext context){ ... }. This is clearly not right, but what should I use?
5 年多之前 回复
csdnceshi70
笑故挽风 Cook Implementation dependent. From my experience major browsers set 'Content-length' (it is required) automatically from the data you supply. 'Connection' header defaults to 'keep-alive' in most cases, which keeps connection open for a while so subsequent requests don't have to reestablish connection again as in case of 'close'. You can try those snippets in the console, using current page URL and inspect request headers using browser's tools or wireshark.
接近 7 年之前 回复
csdnceshi63
elliott.david The answer that has few votes but got marked correct uses two extra headers: http.setRequestHeader("Content-length", params.length); and http.setRequestHeader("Connection", "close");. Are they needed? Are they perhaps only needed on certain browsers? (There is a comment on that other page saying setting the Content-Length header was "exactly what was needed")
接近 7 年之前 回复
csdnceshi70
笑故挽风 Yes, but question was to write JavaScript equivalent of provided form not submit the form using JavaScript.
大约 7 年之前 回复
csdnceshi75
衫裤跑路 FormData takes the form element as its constructor argument, no need to add values indivually
大约 7 年之前 回复

Here is a complete solution with 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>

Ensure that your Backend API can parse JSON.

For example, in Express JS:

import bodyParser from 'body-parser'
app.use(bodyParser.json())
csdnceshi59
ℙℕℤℝ I like that better because it's reasonable and one less detail for someone to start with. Thanks for highlighting it.
2 年多之前 回复
csdnceshi59
ℙℕℤℝ Given the default of true, I am going to remove it from the example and drop this URL for research: developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open
2 年多之前 回复
csdnceshi57
perhaps? It should default to true but I don't know if all browsers respect that
2 年多之前 回复
csdnceshi59
ℙℕℤℝ Should we put true there or just omit that parameter? I will update the answer if you can specify which is preferable.
2 年多之前 回复
csdnceshi57
perhaps? Great, but don't use 'false' value for the async parameter in XMLHttpRequest.open - it's deprecated and will give a warning
2 年多之前 回复

Minimal use of FormData to submit an AJAX request

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

Remarks

  1. This does not fully answer the OP question because it requires the user to click in order to submit the request. But this may be useful to people searching for this kind of simple solution.

  2. This example is very simple and does not support the GET method. If you are interesting by more sophisticated examples, please have a look at the excellent MDN documentation. See also similar answer about XMLHttpRequest to Post HTML Form.

  3. Limitation of this solution: As pointed out by Justin Blank and Thomas Munk (see their comments), FormData is not supported by IE9 and lower, and default browser on Android 2.3.

weixin_41568183
零零乙 works somewhat in IE11 apparently, FWIW...
2 年多之前 回复
csdnceshi72
谁还没个明天 I'm not that experienced with web-development. I've figured out that the POST request is indeed sent when you return false. If true is returned, the original (unwanted) POST request will be send! Your answer is correct, sorry for the confusion.
大约 3 年之前 回复
csdnceshi50
三生石@ Thanks @MarkusL for your feedback. I have updated the answer. I am still surprised that you had to return true. Does your corresponding function submitForm() return true? I hope the answer is correct... Cheers
大约 3 年之前 回复
csdnceshi72
谁还没个明天 Thanks for this solution. I needed to return true in order to actually send the POST request!
大约 3 年之前 回复
csdnceshi50
三生石@ Thanks @Vic for your contribution, I have updated the answer. Cheers ;-)
5 年多之前 回复
csdnceshi54
hurriedly% Elegant solution, but you should specify onsubmit="return submitForm(this);" otherwise the user gets redirected to the URL in the request.
5 年多之前 回复
csdnceshi50
三生石@ Thanks @ThomasMunk for your link :-) We see that FormData is supported by many browsers except IE9 and Android 2.3 (and OperaMini but this last is not widely used). Cheers ;-)
接近 6 年之前 回复
csdnceshi77
狐狸.fox Correct with IE9: caniuse.com/#search=FormData
接近 6 年之前 回复
csdnceshi80
胖鸭 The only thing about this is that I think FormData is not available in IE 9, so it's not going to be usable for a lot of people without a polyfill. developer.mozilla.org/en-US/docs/Web/API/FormData
大约 6 年之前 回复

NO PLUGINS NEEDED!

Just drag any link (i.e. THIS LINK) in BOOKMARK BAR (if you dont see it, enable from Browser Settings), then EDIT that link :

enter image description here

and insert javascript code:

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

That's all! Now you can visit any website, and click that button in BOOKMARK BAR!


NOTE:

The above method sends data using XMLHttpRequest method, so, you have to be on the same domain while triggering the script. That's why I prefer sending data with a simulated FORM SUBMITTING, which can send the code to any domain - here is code for that:

 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); 
weixin_41568184
叼花硬汉 awesome. just wanted some relation while reviewing since it was an answer . now it is an answer plus a gr8 tip for all who drop by. i've reverted votes. cheers
接近 4 年之前 回复
csdnceshi69
YaoRaoLov i wont start arguing with you about the profitability of my answer. however, i have updated my answer, and now there is what you wanted.
接近 4 年之前 回复
weixin_41568131
10.24 And your question really doesn't answer what OP has asked for. BookMarking a HTTP Request... !? I don't see any point relating XmlHttpRequest in your answer :|
大约 4 年之前 回复
weixin_41568131
10.24 I didn't and I couldn't :| I don't have 125 reps :| And if you see my profile you will see I have 136 up votes :| Even after I get the permission to downvote, I will avoid it unless it is neccessary :|
大约 4 年之前 回复
weixin_41568131
10.24 For Mozilla, Can I do something similar to this?
大约 4 年之前 回复

I have faced similar problem, using the same post and and this link I have resolved my issue.

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

This link has completed information.

Use modern JavaScript!

I'd suggest looking into fetch. It is the ES5 equivalent and uses Promises. It is much more readable and easily customizable.

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

More Info:

Mozilla Documentation

Can I Use (88% Mar 2018)

Matt Walsh Tutorial

</div>
csdnceshi72
谁还没个明天 There are plenty of good reasons to use this. I like to mention that. Also, use Babel for transpiling.
接近 2 年之前 回复
csdnceshi63
elliott.david Is there a way to specify Content-Type using the fetch() function?
2 年多之前 回复
csdnceshi61
derek5. If worried about compatibility...Google es6 transpiler... stackoverflow.com/questions/40205547/…. Write it simple. Deploy it compatible. +1 avoid this.
2 年多之前 回复
weixin_41568131
10.24 I avoid this like the plague as well, and so should anyone reading this.
接近 3 年之前 回复
weixin_41568126
乱世@小熊 Fat arrow also doesn't work with this keyword. I like to mention that, but I also secretly hate people that use this, and inheritance architecture instead of function factories. Forgive me, I am node.
接近 3 年之前 回复
weixin_41568131
10.24 Promises are 90% covered. I added function() examples in case you don't prefer =>. You should absolutely be using modern JS to ease the developer experience. Worrying about a small percentage of people stuck on IE isn't worth it unless you are a huge enterprise
接近 3 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 You should avoid using Promises and fat arrows for things this critical to webpage functionality, as many devices do not have browsers that support these features.
接近 3 年之前 回复
csdnceshi52
妄徒之命 Cool! It is 2017, so this should be the accepted answer.
接近 3 年之前 回复
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");
}
csdnceshi54
hurriedly% Hello Hugo, This code is to send data or file with progress upload if browser support it. included all possible events and compatibility browser. It try use the most new object class from browser. It help you?
3 年多之前 回复
csdnceshi64
游.程 Could you explain this code a bit ?
3 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问