【问题标题】:Pure JavaScript Send POST Data Without a Form纯 JavaScript 发送没有表单的 POST 数据
【发布时间】:2011-09-17 18:35:23
【问题描述】:

有没有办法使用 POST 方法发送数据而无需使用表单并且仅使用纯 JavaScript(不是 jQuery $.post())刷新页面?可能是httprequest 或者别的什么(只是现在找不到)?

【问题讨论】:

标签: javascript post httpwebrequest xmlhttprequest http-post


【解决方案1】:

您可以发送它并将数据插入正文:

var xhr = new XMLHttpRequest();
xhr.open("POST", yourUrl, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
    value: value
}));

顺便说一下,获取请求:

var xhr = new XMLHttpRequest();
// we defined the xhr

xhr.onreadystatechange = function () {
    if (this.readyState != 4) return;

    if (this.status == 200) {
        var data = JSON.parse(this.responseText);

        // we get the returned data
    }

    // end of state change: it can be after some time (async)
};

xhr.open('GET', yourUrl, true);
xhr.send();

【讨论】:

【解决方案2】:

Fetch API 旨在简化 GET 请求,但它也可以 POST。

let data = {element: "barium"};

fetch("/post/data/here", {
  method: "POST",
  headers: {'Content-Type': 'application/json'}, 
  body: JSON.stringify(data)
}).then(res => {
  console.log("Request complete! response:", res);
});

如果你和我一样懒惰(或者只是更喜欢快捷方式/助手):

window.post = function(url, data) {
  return fetch(url, {method: "POST", headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data)});
}

// ...

post("post/data/here", {element: "osmium"});

【讨论】:

  • 由于这个答案很简单,我过早地赞成它,它不允许我撤回我的投票。仅当您添加标头时发送数据才有效。 (headers: {'Accept': 'application/json', 'Content-Type': 'application/json'}) 此外,除非您在响应中调用 json() 方法,否则接收数据也不起作用,就像这样: res.json(),它恰好返回另一个你必须解包的承诺。最好使用 async/await 并使用 await 解开所有这些承诺。
  • 获取 API 是当前的方式
  • 谢谢,很有魅力。
【解决方案3】:

您可以按如下方式使用XMLHttpRequest 对象:

xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
xhr.send(someStuff);

该代码会将someStuff 发布到url。只要确保当您创建 XMLHttpRequest 对象时,它将是跨浏览器兼容的。如何做到这一点的例子不胜枚举。

【讨论】:

  • 你能为someStuff写一个例子吗?
  • someStuff = 'param1=val1&param2=val2&param3=val3'
  • 这是一个很好的答案,someStuff 可以是任何你想要的东西,甚至是一个简单的字符串。您可以使用我个人最喜欢的在线服务来查看请求:(requestb.in)
  • application/x-www-form-urlencoded MIME 类型没有charset 参数:iana.org/assignments/media-types/application/…
【解决方案4】:

此外,RESTful 允许您从 POST 请求中获取数据返回

JS(放入 static/hello.html 以通过 Python 服务):

<html><head><meta charset="utf-8"/></head><body>
Hello.

<script>

var xhr = new XMLHttpRequest();
xhr.open("POST", "/postman", true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
    value: 'value'
}));
xhr.onload = function() {
  console.log("HELLO")
  console.log(this.responseText);
  var data = JSON.parse(this.responseText);
  console.log(data);
}

</script></body></html>

Python 服务器(用于测试):

import time, threading, socket, SocketServer, BaseHTTPServer
import os, traceback, sys, json


log_lock           = threading.Lock()
log_next_thread_id = 0

# Local log functiondef


def Log(module, msg):
    with log_lock:
        thread = threading.current_thread().__name__
        msg    = "%s %s: %s" % (module, thread, msg)
        sys.stderr.write(msg + '\n')

def Log_Traceback():
    t   = traceback.format_exc().strip('\n').split('\n')
    if ', in ' in t[-3]:
        t[-3] = t[-3].replace(', in','\n***\n***  In') + '(...):'
        t[-2] += '\n***'
    err = '\n***  '.join(t[-3:]).replace('"','').replace(' File ', '')
    err = err.replace(', line',':')
    Log("Traceback", '\n'.join(t[:-3]) + '\n\n\n***\n*** ' + err + '\n***\n\n')

    os._exit(4)

def Set_Thread_Label(s):
    global log_next_thread_id
    with log_lock:
        threading.current_thread().__name__ = "%d%s" \
            % (log_next_thread_id, s)
        log_next_thread_id += 1


class Handler(BaseHTTPServer.BaseHTTPRequestHandler):

    def do_GET(self):
        Set_Thread_Label(self.path + "[get]")
        try:
            Log("HTTP", "PATH='%s'" % self.path)
            with open('static' + self.path) as f:
                data = f.read()
            Log("Static", "DATA='%s'" % data)
            self.send_response(200)
            self.send_header("Content-type", "text/html")
            self.end_headers()
            self.wfile.write(data)
        except:
            Log_Traceback()

    def do_POST(self):
        Set_Thread_Label(self.path + "[post]")
        try:
            length = int(self.headers.getheader('content-length'))
            req   = self.rfile.read(length)
            Log("HTTP", "PATH='%s'" % self.path)
            Log("URL", "request data = %s" % req)
            req = json.loads(req)
            response = {'req': req}
            response = json.dumps(response)
            Log("URL", "response data = %s" % response)
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.send_header("content-length", str(len(response)))
            self.end_headers()
            self.wfile.write(response)
        except:
            Log_Traceback()


# Create ONE socket.
addr = ('', 8000)
sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(addr)
sock.listen(5)

# Launch 100 listener threads.
class Thread(threading.Thread):
    def __init__(self, i):
        threading.Thread.__init__(self)
        self.i = i
        self.daemon = True
        self.start()
    def run(self):
        httpd = BaseHTTPServer.HTTPServer(addr, Handler, False)

        # Prevent the HTTP server from re-binding every handler.
        # https://stackoverflow.com/questions/46210672/
        httpd.socket = sock
        httpd.server_bind = self.server_close = lambda self: None

        httpd.serve_forever()
[Thread(i) for i in range(10)]
time.sleep(9e9)

控制台日志(chrome):

HELLO
hello.html:14 {"req": {"value": "value"}}
hello.html:16 
{req: {…}}
req
:
{value: "value"}
__proto__
:
Object

控制台日志(火狐):

GET 
http://XXXXX:8000/hello.html [HTTP/1.0 200 OK 0ms]
POST 
XHR 
http://XXXXX:8000/postman [HTTP/1.0 200 OK 0ms]
HELLO hello.html:13:3
{"req": {"value": "value"}} hello.html:14:3
Object { req: Object }

控制台日志(边缘):

HTML1300: Navigation occurred.
hello.html
HTML1527: DOCTYPE expected. Consider adding a valid HTML5 doctype: "<!DOCTYPE html>".
hello.html (1,1)
Current window: XXXXX/hello.html
HELLO
hello.html (13,3)
{"req": {"value": "value"}}
hello.html (14,3)
[object Object]
hello.html (16,3)
   {
      [functions]: ,
      __proto__: { },
      req: {
         [functions]: ,
         __proto__: { },
         value: "value"
      }
   }

Python 日志:

HTTP 8/postman[post]: PATH='/postman'
URL 8/postman[post]: request data = {"value":"value"}
URL 8/postman[post]: response data = {"req": {"value": "value"}}

【讨论】:

    【解决方案5】:

    您可以使用 XMLHttpRequest、获取 API、...

    如果您想使用 XMLHttpRequest,您可以执行以下操作

    var xhr = new XMLHttpRequest();
    xhr.open("POST", url, true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.send(JSON.stringify({
        name: "Deska",
        email: "deska@gmail.com",
        phone: "342234553"
     }));
    xhr.onload = function() {
        var data = JSON.parse(this.responseText);
        console.log(data);
    };
    

    或者如果你想使用 fetch API

    fetch(url, {
        method:"POST",
        body: JSON.stringify({
            name: "Deska",
            email: "deska@gmail.com",
            phone: "342234553"
            })
        }).then(result => {
            // do something with the result
            console.log("Completed with result:", result);
        }).catch(err => {
            // if any error occured, then catch it here
            console.error(err);
        });
    

    【讨论】:

      【解决方案6】:

      有一种简单的方法可以包装您的数据并将其发送到服务器,就像您使用 POST 发送 HTML 表单一样。 你可以使用FormData 对象来做到这一点,如下所示:

      data = new FormData()
      data.set('Foo',1)
      data.set('Bar','boo')
      
      let request = new XMLHttpRequest();
      request.open("POST", 'some_url/', true);
      request.send(data)
      

      现在您可以像处理常规 HTML 表单一样在服务器端处理数据。

      其他信息

      建议您在发送 FormData 时不要设置 Content-Type 标头,因为浏览器会处理这个问题。

      【讨论】:

      • ❗️ FormData 将创建一个多部分表单请求,而不是 application/x-www-form-urlencoded 请求
      • @ccpizza - 感谢您的澄清。由于 OP 没有提到要发布哪种类型的数据,我认为 FormData 是最合适的回答方式。
      【解决方案7】:

      您是否知道 JavaScript 具有用于创建表单和提交表单的内置方法和库?

      我在这里看到很多回复都要求使用 3rd 方库,我认为这太过分了。

      我会在纯 Javascript 中执行以下操作:

      <script>
      function launchMyForm()
      {
         var myForm = document.createElement("FORM");
         myForm.setAttribute("id","TestForm");
         document.body.appendChild(myForm);
      
      // this will create a new FORM which is mapped to the Java Object of myForm, with an id of TestForm. Equivalent to: <form id="TestForm"></form>
      
         var myInput = document.createElement("INPUT");
         myInput.setAttribute("id","MyInput");
         myInput.setAttribute("type","text");
         myInput.setAttribute("value","Heider");
         document.getElementById("TestForm").appendChild(myInput);
         
      // To submit the form: 
         myForm.method = "POST";
         myForm.action = "whatever.aspx";  // or "response.php" 
         myForm.submit();
      
      // This will create an INPUT equivalent to: <INPUT id="MyInput" type="text" value="Heider" /> and then assign it to be inside the TestForm tags. 
      }
      </script>
      

      通过这种方式 (A),您无需依赖第 3 方来完成这项工作。 (B) 所有浏览器都内置,(C) 速度更快,(D) 有效,随时尝试。

      我希望这会有所帮助。

      H

      【讨论】:

      • 我喜欢这个回复。现在您已经创建了一个表单,但是如何发送呢?
      • 你好,我看了我的回复,你说的很对,只是修改了一下,添加了如何提交,希望一切顺利,给我一个呼声,我需要更多的帮助,干杯,Heider。
      【解决方案8】:

      navigator.sendBeacon()

      如果您只需要POST 数据而不需要来自服务器的响应,那么最短的解决方案是使用navigator.sendBeacon()

      const data = JSON.stringify({
        example_1: 123,
        example_2: 'Hello, world!',
      });
      
      navigator.sendBeacon('example.php', data);
      

      【讨论】:

      • 无法在“导航器”上执行“发送信标”:信标仅支持通过 HTTP(S)。
      • navigator.sendBeacon 在我看来并不打算用于此目的。
      【解决方案9】:

      这里最流行的答案没有说明如何从 POST 中取回数据。此外,当向最新版本的 NodeJS 发送数据时,流行的“获取”解决方案在最新版本的 Chrome 中不起作用,除非您传递标头并解开 response.json() 承诺。此外,流行的答案不使用 async/await。

      这是我能想到的最干净、最完整的解决方案。

      async function postJsonData(jsonObject) {
          const response = await fetch("/echo", {
              method: "POST",
              headers: {'Content-Type': 'application/json'},
              body: JSON.stringify(jsonObject)
          });
          
          const actualResponse = await response.json();
      }
      

      【讨论】:

      【解决方案10】:

      这是您(或其他任何人)可以在他们的代码中使用的一个很好的函数:

      function post(url, data) {
          return new Promise((res, rej) => {
              let stringified = "";
              for (const [key, value] of Object.entries(data))
                  stringified += `${stringified != '' ? '&' : ''}${key}=${value}`
      
              const xhr = new XMLHttpRequest();
              xhr.onreadystatechange = () => {
                  if (xhr.readyState == 4)
                      if (xhr.status == 200)
                          res(xhr.responseText)
                      else
                          rej({ code: xhr.status, text: xhr.responseText })
              }
              xhr.open("POST", url, true);
              xhr.setRequestHeader('Content-Type', 'application/json');
              xhr.send(stringified);
          })
      }
      

      【讨论】:

      • resrej 未定义。
      • @Matt,请澄清你的意思。这是您遇到的错误吗?
      • resrej 在第 2 行定义。
      【解决方案11】:
      const data = { username: 'example' };
      
      fetch('https://example.com/profile', {
        method: 'POST', // or 'PUT'
        headers: {
       '           Content-Type': 'application/json',
                 },
        body: JSON.stringify(data),
      })
        .then(response => response.json())
        .then(data => {
            console.log('Success:', data);
           })
       .catch((error) => {
               console.error('Error:', error);
         });
      

      【讨论】:

      • “无效名称错误”
      【解决方案12】:

      你也可以使用这个:https://github.com/floscodes/JS/blob/master/Requests.js

      您可以轻松发送 http-Request。只需使用:

      HttpRequest("https://example.com", method="post", data="yourkey=yourdata");
      

      就是这样!如果网站受 CSRF 保护,它甚至应该可以工作。

      或者只是发送一个 GET-Request 使用

      HttpRequest("https://example.com", method="get");
      

      【讨论】:

        【解决方案13】:

        使用jbezz库的这个函数

        var makeHttpObject = function () {
          try {return new XMLHttpRequest();}
          catch (error) {}
          try {return new ActiveXObject("Msxml2.XMLHTTP");}
          catch (error) {}
          try {return new ActiveXObject("Microsoft.XMLHTTP");}
          catch (error) {}
          throw new Error("Could not create HTTP request object.");
        }
        function SendData(data){
            let type = (data.type ? data.type : "GET")
            let DataS = data.data;
            let url = data.url;
            let func = (data.success ? data.success : function(){})
            let funcE =(data.error ? data.error : function(){})
            let a_syne = (data.asyne ? data.asyne : false); 
            let u = null;
            try{u = new URLSearchParams(DataS).toString();}catch(e){u = Object.keys(DataS).map(function(k) {return encodeURIComponent(k) + '=' + encodeURIComponent(DataS[k])}).join('&')}
            if(type == "GET"){url +="?"+u}
            const xhttp =  makeHttpObject();
            xhttp.onload = function(){func(this.responseText)}
            xmlHttp.onreadystatechange = function() {if (xmlHttp.readyState == 4) 
            {if(xmlHttp.status !== 200){funcE(xmlHttp.statusText)}}}
            xhttp.open(type,url,a_syne);
            xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xhttp.send(u);
        }
        

        使用它来运行:

        SendData({
            url:"YOUR_URL",
            asyne:true,
            type:"POST", // or GET
            data:{
                username:"ali",
                password:"mypass" // Your Data
            },
            success:function(Result){
                console.log(Result)
            },
            error:function(e){
                console.log("We Have Some Error")
            }
        });
        

        或者

        下载jbezz并添加到您的页面。

        下载链接:github.com

        使用:

        $$.api({
                url:"YOUR_URL",
                asyne:true,
                type:"POST", // or GET
                data:{
                    username:"ali",
                    password:"mypass" // Your Data
                },
                success:function(Result){
                    console.log(Result)
                },
                error:function(e){
                    console.log("We Have Some Error")
                }
            });
        

        【讨论】:

        • @José 我尽力了。
        猜你喜欢
        • 2022-11-19
        • 2011-10-09
        • 2015-03-11
        • 2011-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-13
        • 1970-01-01
        相关资源
        最近更新 更多