关于http:JavaScript发布请求,如表单提交

JavaScript post request like a form submit

我正在尝试将浏览器指向其他页面。如果我想要一个GET请求,我可以说

1
document.location.href = 'http://example.com/q=a';

但是,除非我使用POST请求,否则我尝试访问的资源不会正确响应。如果这不是动态生成的,我可能会使用HTML

1
2
3
<form action="http://example.com/" method="POST">
  <input type="hidden" name="q" value="a">
</form>

然后我将从DOM提交表单。

但我真的希望JavaScript代码能让我说

1
post_to_url('http://example.com/', {'q':'a'});

什么是最好的跨浏览器实现?

编辑

对不起,我不清楚。我需要一个改变浏览器位置的解决方案,就像提交表单一样。如果XMLHttpRequest可以实现这一点,则不明显。这不应该是异步的,也不应该使用XML,因此Ajax不是答案。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 /**
 * sends a request to the specified url from a form. this will change the window location.
 * @param {string} path the path to send the post request to
 * @param {object} params the paramiters to add to the url
 * @param {string} [method=post] the method to use on the form
 */


function post(path, params, method) {
    method = method ||"post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type","hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
        }
    }

    document.body.appendChild(form);
    form.submit();
}

例子:

1
post('/contact/', {name: 'Johnny Bravo'});

编辑:既然这已经被否决了这么多,我猜人们会复制粘贴这很多。所以我添加了EDOCX1[0]检查来修复任何无意中的错误。


这将是使用jquery的所选答案的版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Post to the provided URL with the specified parameters.
function post(path, parameters) {
    var form = $('<form></form>');

    form.attr("method","post");
    form.attr("action", path);

    $.each(parameters, function(key, value) {
        var field = $('<input></input>');

        field.attr("type","hidden");
        field.attr("name", key);
        field.attr("value", value);

        form.append(field);
    });

    // The form needs to be a part of the document in
    // order for us to be able to submit it.
    $(document.body).append(form);
    form.submit();
}


@aron answer的简单、快速、肮脏的实现:

1
2
document.body.innerHTML += '<form id="dynForm" action="http://example.com/" method="post"><input type="hidden" name="q" value="a"></form>';
document.getElementById("dynForm").submit();

当然,您应该使用一个JavaScript框架,比如原型或者jQuery…


使用本答案中提供的createElement函数,这是必要的,因为ie的中断在通常使用document.createElement创建的元素上具有name属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function postToURL(url, values) {
    values = values || {};

    var form = createElement("form", {action: url,
                                      method:"POST",
                                      style:"display: none"});
    for (var property in values) {
        if (values.hasOwnProperty(property)) {
            var value = values[property];
            if (value instanceof Array) {
                for (var i = 0, l = value.length; i < l; i++) {
                    form.appendChild(createElement("input", {type:"hidden",
                                                             name: property,
                                                             value: value[i]}));
                }
            }
            else {
                form.appendChild(createElement("input", {type:"hidden",
                                                         name: property,
                                                         value: value}));
            }
        }
    }
    document.body.appendChild(form);
    form.submit();
    document.body.removeChild(form);
}


Rakesh Pai的回答是惊人的,但当我试图用一个名为submit的字段发布一个表单时(在Safari中),会出现一个问题。例如,post_to_url("http://google.com/",{ submit:"submit" } );。我稍微修补了这个函数,以绕过这个可变空间碰撞。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    function post_to_url(path, params, method) {
        method = method ||"post";

        var form = document.createElement("form");

        //Move the submit function to another variable
        //so that it doesn't get overwritten.
        form._submit_function_ = form.submit;

        form.setAttribute("method", method);
        form.setAttribute("action", path);

        for(var key in params) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type","hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
        }

        document.body.appendChild(form);
        form._submit_function_(); //Call the renamed function.
    }
    post_to_url("http://google.com/", { submit:"submit" } ); //Works!


不可以。您不能像提交表单那样拥有JavaScript发布请求。

您可以使用HTML格式的表单,然后用JavaScript提交它。(如本页多次所述)。

您可以自己创建HTML,不需要JavaScript来编写HTML。如果有人建议,那就太傻了。

1
2
3
<form id="ninja" action="http://example.com/" method="POST">
  <input id="donaldduck" type="hidden" name="q" value="a">
</form>

您的函数只是按照您想要的方式配置表单。

1
2
3
4
5
6
function postToURL(a,b,c){
   document.getElementById("ninja").action     = a;
   document.getElementById("donaldduck").name  = b;
   document.getElementById("donaldduck").value = c;
   document.getElementById("ninja").submit();
}

然后,像这样使用。

1
postToURL("http://example.com/","q","a");

但我会忽略这个功能,然后就这么做。

1
2
document.getElementById('donaldduck').value ="a";
document.getElementById("ninja").submit();

最后,样式决定在ccs文件中进行。

1
2
3
#ninja{
  display:none;
}

就我个人而言,我认为表格应该按姓名填写,但现在这并不重要。


如果已经安装了原型,则可以拧紧代码以生成和提交隐藏表单,如下所示:

1
2
3
4
5
6
 var form = new Element('form',
                        {method: 'post', action: 'http://example.com/'});
 form.insert(new Element('input',
                         {name: 'q', value: 'a', type: 'hidden'}));
 $(document.body).insert(form);
 form.submit();

这是Rakesh的答案,但支持数组(在形式上很常见):

纯JavaScript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function post_to_url(path, params, method) {
    method = method ||"post"; // Set method to post by default, if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    var addField = function( key, value ){
        var hiddenField = document.createElement("input");
        hiddenField.setAttribute("type","hidden");
        hiddenField.setAttribute("name", key);
        hiddenField.setAttribute("value", value );

        form.appendChild(hiddenField);
    };

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            if( params[key] instanceof Array ){
                for(var i = 0; i < params[key].length; i++){
                    addField( key, params[key][i] )
                }
            }
            else{
                addField( key, params[key] );
            }
        }
    }

    document.body.appendChild(form);
    form.submit();
}

哦,这里是jquery版本:(代码略有不同,但归根结底是相同的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function post_to_url(path, params, method) {
    method = method ||"post"; // Set method to post by default, if not specified.

    var form = $(document.createElement("form" ))
        .attr( {"method": method,"action": path} );

    $.each( params, function(key,value){
        $.each( value instanceof Array? value : [value], function(i,val){
            $(document.createElement("input"))
                .attr({"type":"hidden","name": key,"value": val })
                .appendTo( form );
        });
    } );

    form.appendTo( document.body ).submit();
}


一种解决方案是生成表单并提交它。一个实现是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function post_to_url(url, params) {
    var form = document.createElement('form');
    form.action = url;
    form.method = 'POST';

    for (var i in params) {
        if (params.hasOwnProperty(i)) {
            var input = document.createElement('input');
            input.type = 'hidden';
            input.name = i;
            input.value = params[i];
            form.appendChild(input);
        }
    }

    form.submit();
}

所以我可以用一个简单的

1
javascript:post_to_url('http://is.gd/create.php', {'URL': location.href});


好吧,希望我能读完所有其他的帖子,这样我就不会浪费时间从RakeshPai的答案中创造出这个。这里有一个递归的解决方案,可以处理数组和对象。不依赖jquery。

添加了一个段来处理应该像数组一样提交整个表单的情况。(即在项目列表周围没有包装对象)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
 * Posts javascript data to a url using form.submit().  
 * Note: Handles json and arrays.
 * @param {string} path - url where the data should be sent.
 * @param {string} data - data as javascript object (JSON).
 * @param {object} options -- optional attributes
 *  {
 *    {string} method: get/post/put/etc,
 *    {string} arrayName: name to post arraylike data.  Only necessary when root data object is an array.
 *  }
 * @example postToUrl('/UpdateUser', {Order {Id: 1, FirstName: 'Sally'}});
 */

function postToUrl(path, data, options) {
    if (options === undefined) {
        options = {};
    }

    var method = options.method ||"post"; // Set method to post by default if not specified.

    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    function constructElements(item, parentString) {
        for (var key in item) {
            if (item.hasOwnProperty(key) && item[key] != null) {
                if (Object.prototype.toString.call(item[key]) === '[object Array]') {
                    for (var i = 0; i < item[key].length; i++) {
                        constructElements(item[key][i], parentString + key +"[" + i +"].");
                    }
                } else if (Object.prototype.toString.call(item[key]) === '[object Object]') {
                    constructElements(item[key], parentString + key +".");
                } else {
                    var hiddenField = document.createElement("input");
                    hiddenField.setAttribute("type","hidden");
                    hiddenField.setAttribute("name", parentString + key);
                    hiddenField.setAttribute("value", item[key]);
                    form.appendChild(hiddenField);
                }
            }
        }
    }

    //if the parent 'data' object is an array we need to treat it a little differently
    if (Object.prototype.toString.call(data) === '[object Array]') {
        if (options.arrayName === undefined) console.warn("Posting array-type to url will doubtfully work without an arrayName defined in options.");
        //loop through each array item at the parent level
        for (var i = 0; i < data.length; i++) {
            constructElements(data[i], (options.arrayName ||"") +"[" + i +"].");
        }
    } else {
        //otherwise treat it normally
        constructElements(data,"");
    }

    document.body.appendChild(form);
    form.submit();
};


这里有三个选项。

  • 标准的javascript回答:使用一个框架!大多数Ajax框架都将为您抽象出一个简单的方法来发布xmlhttpRequest。

  • 自己发出xmlhttprequest请求,将post传递到open方法,而不是get。(有关在xmlhttprequest(ajax)中使用post方法的详细信息。)

  • 通过javascript,动态地创建一个表单,添加一个操作,添加您的输入,然后提交。


  • 我会按照其他人的建议走Ajax路线,比如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    var xmlHttpReq = false;

    var self = this;
    // Mozilla/Safari
    if (window.XMLHttpRequest) {
        self.xmlHttpReq = new XMLHttpRequest();
    }
    // IE
    else if (window.ActiveXObject) {
        self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
    }

    self.xmlHttpReq.open("POST","YourPageHere.asp", true);
    self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

    self.xmlHttpReq.setRequestHeader("Content-length", QueryString.length);



    self.xmlHttpReq.send("?YourQueryString=Value");


    下面是我如何使用jquery编写它。在Firefox和Internet Explorer中测试。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    function postToUrl(url, params, newWindow) {
        var form = $('<form>');
        form.attr('action', url);
        form.attr('method', 'POST');
        if(newWindow){ form.attr('target', '_blank');
      }

      var addParam = function(paramName, paramValue) {
          var input = $('<input type="hidden">');
          input.attr({ 'id':     paramName,
                     'name':   paramName,
                     'value':  paramValue });
          form.append(input);
        };

        // Params is an Array.
        if(params instanceof Array){
            for(var i=0; i<params.length; i++) {
                addParam(i, params[i]);
            }
        }

        // Params is an Associative array or Object.
        if(params instanceof Object) {
            for(var key in params){
                addParam(key, params[key]);
            }
        }

        // Submit the form, then remove it from the page
        form.appendTo(document.body);
        form.submit();
        form.remove();
    }


    最简单的方法是使用Ajax Post请求:

    1
    2
    3
    4
    5
    6
    7
    $.ajax({
        type:"POST",
        url: 'http://www.myrestserver.com/api',
        data: data,
        success: success,
        dataType: dataType
        });

    在哪里?

    • 数据是一个对象
    • 数据类型是服务器预期的数据(XML,JSON、脚本、文本、HTML)
    • url是REST服务器的地址或服务器端接受HTTP-POST的任何函数。

    然后在成功处理程序中,使用window.location之类的东西重定向浏览器。


    原型库包含一个hashtable对象,方法是".to query string()",它允许您轻松地将javascript对象/结构转换为查询字符串样式的字符串。由于post要求请求的"body"是一个查询字符串格式的字符串,因此允许Ajax请求作为post正常工作。下面是一个使用原型的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    $req = new Ajax.Request("http://foo.com/bar.php",{
        method: 'post',
        parameters: $H({
            name: 'Diodeus',
            question: 'JavaScript posts a request like a form request',
            ...
        }).toQueryString();
    };


    在我的情况下,这非常有效:

    1
    document.getElementById("form1").submit();

    您可以在以下功能中使用它:

    1
    2
    3
    function formSubmit() {
         document.getElementById("frmUserList").submit();
    }

    使用它,您可以发布输入的所有值。


    FormObject是一个选项。但现在大多数浏览器都不支持FormObject。


    还有另一个递归解决方案,因为其他一些方案似乎被破坏了(我没有测试所有这些方案)。这个依赖于lodash 3.x和es6(不需要jquery):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    function createHiddenInput(name, value) {
        let input = document.createElement('input');
        input.setAttribute('type','hidden');
        input.setAttribute('name',name);
        input.setAttribute('value',value);
        return input;
    }

    function appendInput(form, name, value) {
        if(_.isArray(value)) {
            _.each(value, (v,i) => {
                appendInput(form, `${name}[${i}]`, v);
            });
        } else if(_.isObject(value)) {
            _.forOwn(value, (v,p) => {
                appendInput(form, `${name}[${p}]`, v);
            });
        } else {
            form.appendChild(createHiddenInput(name, value));
        }
    }

    function postToUrl(url, data) {
        let form = document.createElement('form');
        form.setAttribute('method', 'post');
        form.setAttribute('action', url);

        _.forOwn(data, (value, name) => {
            appendInput(form, name, value);
        });

        form.submit();
    }

    我的解决方案将对深度嵌套的对象进行编码,这与@rakeshpai当前接受的解决方案不同。

    它使用"qs"npm库及其stringify函数将嵌套对象转换为参数。

    虽然您应该能够通过修改传递给stringify的选项来修改Rails后端,使其能够在需要的任何后端工作,但这段代码在Rails后端工作得很好。Rails要求将ArrayFormat设置为"括号"。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import qs from"qs"

    function normalPost(url, params) {
      var form = document.createElement("form");
      form.setAttribute("method","POST");
      form.setAttribute("action", url);

      const keyValues = qs
        .stringify(params, { arrayFormat:"brackets", encode: false })
        .split("&")
        .map(field => field.split("="));

      keyValues.forEach(field => {
        var key = field[0];
        var value = field[1];
        var hiddenField = document.createElement("input");
        hiddenField.setAttribute("type","hidden");
        hiddenField.setAttribute("name", key);
        hiddenField.setAttribute("value", value);
        form.appendChild(hiddenField);
      });
      document.body.appendChild(form);
      form.submit();
    }

    例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    normalPost("/people/new", {
          people: [
            {
              name:"Chris",
              address:"My address",
              dogs: ["Jordan","Elephant Man","Chicken Face"],
              information: { age: 10, height:"3 meters" }
            },
            {
              name:"Andrew",
              address:"Underworld",
              dogs: ["Doug","Elf","Orange"]
            },
            {
              name:"Julian",
              address:"In a hole",
              dogs: ["Please","Help"]
            }
          ]
        });

    生成这些轨道参数:

    1
    2
    3
    4
    5
    {"authenticity_token"=>"...",
    "people"=>
      [{"name"=>"Chris","address"=>"My address","dogs"=>["Jordan","Elephant Man","Chicken Face"],"information"=>{"age"=>"10","height"=>"3 meters"}},
       {"name"=>"Andrew","address"=>"Underworld","dogs"=>["Doug","Elf","Orange"]},
       {"name"=>"Julian","address"=>"In a hole","dogs"=>["Please","Help"]}]}


    我使用Doopt.FraseJava和循环它来获取表单中的所有元素,然后通过XHTTP发送。这是我的javascript/ajax提交解决方案(以包含所有HTML的示例为例):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
              <!DOCTYPE html>
               <html>
               <body>
               <form>
           First name: <input type="text" name="fname" value="Donald">
            Last name: <input type="text" name="lname" value="Duck">
              Addr1: <input type="text" name="add" value="123 Pond Dr">
               City: <input type="text" name="city" value="Duckopolis">
          </form>



               <button onclick="smc()">Submit</button>

                       
                 function smc() {
                      var http = new XMLHttpRequest();
                           var url ="yourphpfile.php";
                         var x = document.forms[0];
                              var xstr ="";
                             var ta ="";
                        var tb ="";
                    var i;
                   for (i = 0; i < x.length; i++) {
         if (i==0){ta = x.elements[i].name+"="+ x.elements[i].value;}else{
           tb = tb+"&"+ x.elements[i].name +"=" + x.elements[i].value;
                 } }

               xstr = ta+tb;
          http.open("POST", url, true);
           http.setRequestHeader("Content-type","application/x-www-form-urlencoded");

          http.onreadystatechange = function() {
              if(http.readyState == 4 && http.status == 200) {

            // do whatever you want to with the html output response here

                    }

                   }
                http.send(xstr);

                  }
             

             </body>
         </html>

    您可以使用DHTML动态添加表单,然后提交。


    这就像是艾伦的第二个选择(上图)。如何实例化httpobj将留待练习。

    1
    2
    3
    4
    httpobj.open("POST", url, true);
    httpobj.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
    httpobj.onreadystatechange=handler;
    httpobj.send(post);

    您可以使用类似jquery的库及其$.Post方法。


    这是基于使用jquery的beausd代码。它得到了改进,因此可以递归地在对象上工作。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    function post(url, params, urlEncoded, newWindow) {
        var form = $('<form />').hide();
        form.attr('action', url)
            .attr('method', 'POST')
            .attr('enctype', urlEncoded ? 'application/x-www-form-urlencoded' : 'multipart/form-data');
        if(newWindow) form.attr('target', '_blank');

        function addParam(name, value, parent) {
            var fullname = (parent.length > 0 ? (parent + '[' + name + ']') : name);
            if(value instanceof Object) {
                for(var i in value) {
                    addParam(i, value[i], fullname);
                }
            }
            else $('<input type="hidden" />').attr({name: fullname, value: value}).appendTo(form);
        };

        addParam('', params, '');

        $('body').append(form);
        form.submit();
    }


    用于使用post或get重定向的jquery插件:

    https://github.com/mgalante/jquery.redirect/blob/master/jquery.redirect.js网站

    要进行测试,请包含上述.js文件或将类复制/粘贴到代码中,然后在此处使用代码,将"args"替换为变量名,将"values"替换为这些变量的值:

    1
    $.redirect('demo.php', {'arg1': 'value1', 'arg2': 'value2'});


    我用来将用户自动发布和定向到另一个页面的方法是只编写一个隐藏的表单,然后自动提交它。请确保隐藏的表单在网页上绝对不占用任何空间。代码应该是这样的:

    1
    2
    3
    4
    5
    6
    7
    8
        <form name="form1" method="post" action="somepage.php">
        <input name="fielda" type="text" id="fielda" type="hidden">

        <textarea name="fieldb" id="fieldb" cols="" rows="" style="display:none"></textarea>
    </form>
        document.getElementById('fielda').value="some text for field a";
        document.getElementById('fieldb').innerHTML="some text for multiline fieldb";
        form1.submit();

    自动提交申请

    自动提交的应用程序将把用户自动放入另一页的表单值定向回该页。这样的应用程序如下:

    1
    2
    3
    4
    5
    6
    7
    8
    fieldapost=<?php echo $_post['fielda'];>
    if (fieldapost !="") {
    document.write("<form name='form1' method='post' action='previouspage.php'>
      <input name='fielda' type='text' id='fielda' type='hidden'>
    </form>"
    );
    document.getElementById('fielda').value=fieldapost;
    form1.submit();
    }

    您可以使用jquery触发器方法提交表单,就像按按钮一样,

    1
    $('form').trigger('submit')

    它将在浏览器上提交。


    我就是这样做的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function redirectWithPost(url, data){
            var form = document.createElement('form');
            form.method = 'POST';
            form.action = url;

            for(var key in data){
                var input = document.createElement('input');
                input.name = key;
                input.value = data[key];
                input.type = 'hidden';
                form.appendChild(input)
            }
            document.body.appendChild(form);
            form.submit();
        }

    您可以调用Ajax(可能使用库,如使用prototype.js或jquery)。Ajax可以处理get和post选项。