Java 从发送到serversocket的html表单中读取POST数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3033755/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:48:50  来源:igfitidea点击:

Reading POST data from html form sent to serversocket

javaxmlsocketspostserversocket

提问by qqryq

i try to write simplest possible server app in Java, displaying html form with textarea input, which after submitting gives me possibility to parse xml typed in that textarea. For now i build simple serversocket based server like that:

我尝试用 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();
  }
}

After form (textarea with xml and one additional text input) is submitted in 'gets' String-type variable I have Urlencoded values of my variables (also displayed on the screen, it looks like that:

在“gets”字符串类型变量中提交表单(带有 xml 的 textarea 和一个附加文本输入)后,我的变量的 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 

What can i do to change GET to POST method (if i simply change it in form and than put " if (str.contains("POST")){" it gives me string like

我能做些什么来改变 GET 到 POST 方法(如果我只是改变它的形式而不是把“ if (str.contains("POST")){" 它给我这样的字符串

gets = POST / HTTP/1.1

with no variables. And after that, how i can use xml from my textarea field (called 'we')?

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

回答by irreputable

POST data is not in the first line. Print all lines and you'll see. It's actually immediately after a blank line.

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

回答by cygri

A typical HTTP POST request looks like this:

典型的 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

The first line contains the method (typically GET or POST, but there's more, like HEAD, PUT, DELETE), the request URI, and the protocol version. Then there are a number of request headers, which may not be so important for a simple server. If the method is one that takes a request body (POST and PUT), then after the headers there's a blank line followed by the request body. In the case of a POST from an HTML form, the body will consists of key=valuepairs for all form elements, joined by &. The values will be %-encoded.

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

You just need to take care of properly parsing the entire request.

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

You should be aware that line endings in HTTP are supposed to be Windows-style (\r\n). The readline()method might interpret this as two linebreaks, so it might look like there's an empty line between each of the real lines.

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

回答by Alexmelyon

This is my implementation for read POST body:

这是我读取 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());
}

I do it for android and publishProgresin my case means:

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

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

回答by VSarin

As there is a blank line following the headers, here is my relatively simple way of getting the post payload data, after having read the header information using the readLine()method of BufferedReader.

由于标题后面有一个空行,这是我在使用readLine()BufferedReader 方法读取标题信息后获取后期有效负载数据的相对简单的方法。

//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())

回答by prash

From this-

这个-

We need to first read headers and then read again from the same BufferedReader using actual content length provided in the header section :-

我们需要首先读取标题,然后使用标题部分中提供的实际内容长度从同一个 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

HTH