【问题标题】:Reading POST data from html form sent to serversocket从发送到 serversocket 的 html 表单中读取 POST 数据
【发布时间】:2018-02-23 22:40:58
【问题描述】:

我尝试用 Java 编写最简单的服务器应用程序,显示带有 textarea 输入的 html 表单,提交后让我可以解析在该 textarea 中键入的 xml。现在我像这样构建简单的基于 serversocket 的服务器:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class WebServer {

  protected void start() {
    ServerSocket s;
    String gets = "";
    System.out.println("Start on port 80");
    try {
      // create the main server socket
      s = new ServerSocket(80);
    } catch (Exception e) {
      System.out.println("Error: " + e);
      return;
    }

    System.out.println("Waiting for connection");
    for (;;) {
      try {
        // wait for a connection
        Socket remote = s.accept();
        // remote is now the connected socket
        System.out.println("Connection, sending data.");
        BufferedReader in = new BufferedReader(new InputStreamReader(
            remote.getInputStream()));
        PrintWriter out = new PrintWriter(remote.getOutputStream());

        String str = ".";

        while (!str.equals("")) {
          str = in.readLine();
          if (str.contains("GET")){
            gets = str;
            break;
          }
        }

        out.println("HTTP/1.0 200 OK");
        out.println("Content-Type: text/html");
        out.println("");
        // Send the HTML page
        String method = "get";
        out.print("<html><form method="+method+">");
        out.print("<textarea name=we></textarea></br>");
        out.print("<input type=text name=a><input type=submit></form></html>");
        out.println(gets);
        out.flush();

        remote.close();
      } catch (Exception e) {
        System.out.println("Error: " + e);
      }
    }
  }

  public static void main(String args[]) {
    WebServer ws = new WebServer();
    ws.start();
  }
}

在“gets”字符串类型变量中提交表单(带有 xml 的文本区域和一个额外的文本输入)后,我有我的变量的 Urlencoded 值(也显示在屏幕上,看起来像这样:

gets = GET /?we=%3Cnetwork+ip_addr%3D%2210.0.0.0%2F8%22+save_ip%3D%22true%22%3E%0D%0A%3Csubnet+interf_used%3D%22200%22+name%3D%22lan1%22+%2F%3E%0D%0A%3Csubnet+interf_used%3D%22254%22+name%3D%22lan2%22+%2F%3E%0D%0A%3C%2Fnetwork%3E&a=fooBar HTTP/1.1 

我能做些什么来改变 GET 到 POST 方法(如果我只是在表单中改变它而不是输入“if(str.contains(“POST”)){“它给了我类似的字符串

gets = POST / HTTP/1.1

没有变量。之后,我如何使用我的 textarea 字段(称为“我们”)中的 xml?

【问题讨论】:

  • 嗨 qqryq。我有相同的代码。你知道如何阅读 POST 正文吗?正如cygri所说,我试图在循环中运行第二个,但是方法 inputStream.read 或 bufferedReader.readline 阻塞了我的线程。您如何阅读 POST 正文?
  • 哦,我意识到了!我需要阅读“Content-Length:”标题并执行循环到这个长度。

标签: java xml sockets post serversocket


【解决方案1】:

由于headers后面有一个空行,这是我在使用BufferedReader的readLine()方法读取header信息后获取post payload数据的相对简单的方法。

//socket is an instance of Socket
InputStream is = socket.getInputStream();
InputStreamReader isReader = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isReader);

//code to read and print headers
String headerLine = null;
    while((headerLine = br.readLine()).length() != 0){
        System.out.println(headerLine);
    }

//code to read the post payload data
StringBuilder payload = new StringBuilder();
        while(br.ready()){
            payload.append((char) br.read());
            }
System.out.println("Payload data is: "+payload.toString())

【讨论】:

  • 非常感谢...这就是我要找的。 . . .
  • 这很好用。但它不仅返回数据,还返回整个发布请求描述。有没有办法只获取数据。还是我们必须按照常规方式进行字符串拆分?
【解决方案2】:

这是我的读取 POST 正文的实现:

try {
    Socket socket = params[0];
    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    // read request
    String line;
    line = in.readLine();
    StringBuilder raw = new StringBuilder();
    raw.append("" + line);
    boolean isPost = line.startsWith("POST");
    int contentLength = 0;
    while (!(line = in.readLine()).equals("")) {
        raw.append('\n' + line);
        if (isPost) {
            final String contentHeader = "Content-Length: ";
            if (line.startsWith(contentHeader)) {
                contentLength = Integer.parseInt(line.substring(contentHeader.length()));
            }
        }
    }
    StringBuilder body = new StringBuilder();
    if (isPost) {
        int c = 0;
        for (int i = 0; i < contentLength; i++) {
            c = in.read();
            body.append((char) c);
            Log.d("JCD", "POST: " + ((char) c) + " " + c);
        }
    }
    raw.append(body.toString());
    publishProgress(raw.toString());
    // send response
    out.write("HTTP/1.1 200 OK\r\n");
    out.write("Content-Type: text/html\r\n");
    out.write("\r\n");
    out.write(new Date().toString());
    if (isPost) {
        out.write("<br><u>" + body.toString() + "</u>");
    } else {
        out.write("<form method='POST'>");
        out.write("<input name='name' type='text'/>");
        out.write("<input type='submit'/>");
        out.write("</form>");
    }
    //
    // do not in.close();
    out.flush();
    out.close();
    socket.close();
    //
} catch (Exception e) {
    e.printStackTrace();
    StringWriter sw = new StringWriter();
    e.printStackTrace(new PrintWriter(sw));
    publishProgress('\n' + sw.toString());
}

我是为 android 做的,publishProgres 在我的情况下意味着:

protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        instance.logTextView.append(values[0]);
    }

【讨论】:

  • 基本上,第一次阅读应该拾取所有标题行。之后,应该使用 Content-Length 标头来预先知道应该读取多少个字符,然后简单地继续进行进一步处理
【解决方案3】:

典型的 HTTP POST 请求如下所示:

POST / HTTP/1.1
Host: www.example.com
Accept: text/html,*/*;q=0.5
User-Agent: BrowserName/1.0
Referer: http://www.example.com/
Content-type: application/x-www-form-urlencoded; charset=utf-8

foo=1&bar=2

第一行包含方法(通常是 GET 或 POST,但还有更多,例如 HEAD、PUT、DELETE)、请求 URI 和协议版本。然后是一些请求头,对于一个简单的服务器来说可能不是那么重要。如果该方法采用请求正文(POST 和 PUT),则在标头之后有一个空行,后跟请求正文。对于来自 HTML 表单的 POST,正文将由所有表单元素的 key=value 对组成,并由 &amp; 连接。这些值将被 % 编码。

您只需要注意正确解析整个请求。

您应该知道 HTTP 中的行尾应该是 Windows 样式的 (\r\n)。 readline() 方法可能会将其解释为两个换行符,因此看起来每条实际行之间都有一个空行。

【讨论】:

  • 好的,但是当我的 while 停在第一个空行上时如何获取该数据?
  • 重写您的 while 循环,使其不会在第一行停止。您需要这方面的帮助吗?
【解决方案4】:

POST 数据不在第一行。打印所有行,你会看到。它实际上是在一个空行之后。

【讨论】:

  • 好的,但是如果我有 'while (!str.equals("")) {' 语句,我该如何提示所有内容?忽略第一个空行并停在另一个空行上?
【解决方案5】:

来自this -

我们需要先读取标题,然后使用标题部分中提供的实际内容长度从同一个 BufferedReader 再次读取:-

BufferedReader in = new BufferedReader(new InputStreamReader(is));
String line;
line = in.readLine();
while ((line = in.readLine()) != null && (line.length() != 0)) {
    System.out.println("HTTP-HEADER: " + line);
    if (line.indexOf("Content-Length:") > -1) {
    postDataI = new Integer(
        line.substring(
            line.indexOf("Content-Length:") + 16,
            line.length())).intValue();
    }
}
String postData = "";
// read the post data
if (postDataI > 0) {
    char[] charArray = new char[postDataI];
    in.read(charArray, 0, postDataI);
    postData = new String(charArray);
}

HTH

【讨论】:

    猜你喜欢
    • 2014-03-24
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 2012-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多