Senden einer HTTP-POST-Anfrage in Java

294

Nehmen wir diese URL an ...

http://www.example.com/page.php?id=10            

(Hier muss die ID in einer POST-Anfrage gesendet werden.)

Ich möchte das id = 10an den Server sendenpage.php , der es in einer POST-Methode akzeptiert.

Wie kann ich das in Java machen?

Ich habe es versucht:

URL aaa = new URL("http://www.example.com/page.php");
URLConnection ccc = aaa.openConnection();

Aber ich kann immer noch nicht herausfinden, wie ich es per POST senden soll

Jazz
quelle

Antworten:

339

Aktualisierte Antwort:

Da einige der Klassen in der ursprünglichen Antwort in der neueren Version von Apache HTTP Components veraltet sind, veröffentliche ich dieses Update.

By the way, können Sie die vollständige Dokumentation für weitere Beispiele zugreifen hier .

HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("http://www.a-domain.com/foo/");

// Request parameters and other properties.
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("param-1", "12345"));
params.add(new BasicNameValuePair("param-2", "Hello!"));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));

//Execute and get the response.
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();

if (entity != null) {
    try (InputStream instream = entity.getContent()) {
        // do something useful
    }
}

Ursprüngliche Antwort:

Ich empfehle Apache HttpClient zu verwenden. Es ist schneller und einfacher zu implementieren.

HttpPost post = new HttpPost("http://jakarata.apache.org/");
NameValuePair[] data = {
    new NameValuePair("user", "joe"),
    new NameValuePair("password", "bloggs")
};
post.setRequestBody(data);
// execute method and handle any error responses.
...
InputStream in = post.getResponseBodyAsStream();
// handle response.

Weitere Informationen finden Sie unter folgender URL: http://hc.apache.org/

mhshams
quelle
25
Nachdem er eine Weile versucht , meine Hände auf PostMethodsie sich jetzt scheinen tatsächlich genannt HttpPostwie pro stackoverflow.com/a/9242394/1338936 - nur für jedermann daran , diese Antwort , wie ich :) tat
Martin Lyne
1
@ Juan (und Martin Lyne) danke für die Kommentare. Ich habe gerade die Antwort aktualisiert.
Mhshams
Verwendet Ihre überarbeitete Antwort immer noch hc.apache.org?
Djangofan
@ Djangofan ja. Auch in der überarbeiteten Antwort gibt es einen Link zu apache-hc.
Mhshams
6
Sie sollten die importierten
Bibliotheken
191

Das Senden einer POST-Anfrage ist in Vanilla Java einfach. Beginnend mit a URLmüssen wir es nicht in ein URLConnectionusing konvertieren url.openConnection();. Danach müssen wir es in a HttpURLConnectionumwandeln, damit wir auf seine setRequestMethod()Methode zugreifen können , um unsere Methode festzulegen. Wir sagen schließlich, dass wir Daten über die Verbindung senden werden.

URL url = new URL("https://www.example.com/login");
URLConnection con = url.openConnection();
HttpURLConnection http = (HttpURLConnection)con;
http.setRequestMethod("POST"); // PUT is another valid option
http.setDoOutput(true);

Wir müssen dann angeben, was wir senden werden:

Senden eines einfachen Formulars

Ein normaler POST, der von einem http-Formular stammt, hat ein genau definiertes Format. Wir müssen unsere Eingabe in dieses Format konvertieren:

Map<String,String> arguments = new HashMap<>();
arguments.put("username", "root");
arguments.put("password", "sjh76HSn!"); // This is a fake password obviously
StringJoiner sj = new StringJoiner("&");
for(Map.Entry<String,String> entry : arguments.entrySet())
    sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" 
         + URLEncoder.encode(entry.getValue(), "UTF-8"));
byte[] out = sj.toString().getBytes(StandardCharsets.UTF_8);
int length = out.length;

Wir können dann unseren Formularinhalt mit den richtigen Überschriften an die http-Anfrage anhängen und senden.

http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
http.connect();
try(OutputStream os = http.getOutputStream()) {
    os.write(out);
}
// Do something with http.getInputStream()

JSON senden

Wir können json auch mit Java senden, das ist auch einfach:

byte[] out = "{\"username\":\"root\",\"password\":\"password\"}" .getBytes(StandardCharsets.UTF_8);
int length = out.length;

http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
http.connect();
try(OutputStream os = http.getOutputStream()) {
    os.write(out);
}
// Do something with http.getInputStream()

Denken Sie daran , dass verschiedene Server unterschiedliche Content-Typen für json akzeptieren, sehen diese Frage.


Senden von Dateien mit Java-Post

Das Senden von Dateien kann als schwieriger angesehen werden, da das Format komplexer ist. Wir werden auch Unterstützung für das Senden der Dateien als Zeichenfolge hinzufügen, da wir die Datei nicht vollständig im Speicher puffern möchten.

Dazu definieren wir einige Hilfsmethoden:

private void sendFile(OutputStream out, String name, InputStream in, String fileName) {
    String o = "Content-Disposition: form-data; name=\"" + URLEncoder.encode(name,"UTF-8") 
             + "\"; filename=\"" + URLEncoder.encode(filename,"UTF-8") + "\"\r\n\r\n";
    out.write(o.getBytes(StandardCharsets.UTF_8));
    byte[] buffer = new byte[2048];
    for (int n = 0; n >= 0; n = in.read(buffer))
        out.write(buffer, 0, n);
    out.write("\r\n".getBytes(StandardCharsets.UTF_8));
}

private void sendField(OutputStream out, String name, String field) {
    String o = "Content-Disposition: form-data; name=\"" 
             + URLEncoder.encode(name,"UTF-8") + "\"\r\n\r\n";
    out.write(o.getBytes(StandardCharsets.UTF_8));
    out.write(URLEncoder.encode(field,"UTF-8").getBytes(StandardCharsets.UTF_8));
    out.write("\r\n".getBytes(StandardCharsets.UTF_8));
}

Mit diesen Methoden können wir dann eine mehrteilige Post-Anfrage wie folgt erstellen:

String boundary = UUID.randomUUID().toString();
byte[] boundaryBytes = 
           ("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8);
byte[] finishBoundaryBytes = 
           ("--" + boundary + "--").getBytes(StandardCharsets.UTF_8);
http.setRequestProperty("Content-Type", 
           "multipart/form-data; charset=UTF-8; boundary=" + boundary);

// Enable streaming mode with default settings
http.setChunkedStreamingMode(0); 

// Send our fields:
try(OutputStream out = http.getOutputStream()) {
    // Send our header (thx Algoman)
    out.write(boundaryBytes);

    // Send our first field
    sendField(out, "username", "root");

    // Send a seperator
    out.write(boundaryBytes);

    // Send our second field
    sendField(out, "password", "toor");

    // Send another seperator
    out.write(boundaryBytes);

    // Send our file
    try(InputStream file = new FileInputStream("test.txt")) {
        sendFile(out, "identification", file, "text.txt");
    }

    // Finish the request
    out.write(finishBoundaryBytes);
}


// Do something with http.getInputStream()
Ferrybig
quelle
5
Dieser Beitrag ist nützlich, aber ziemlich fehlerhaft. Ich habe 2 Tage gebraucht, um es zum Laufen zu bringen. Damit es funktioniert, müssen Sie StandartCharsets.UTF8 durch StandardCharsets.UTF_8 ersetzen. borderBytes und finishBoundaryBytes müssen zwei zusätzliche Bindestriche abrufen, die NICHT im Inhaltstyp übertragen werden. also borderBytes = ("-" + border + "\ r \ n"). get ... Sie müssen die borderBytes auch einmal übertragen VOR dem ersten Feld oder dem ersten Feld wird ignoriert!
Algoman
Warum out.write(finishBoundaryBytes);Linie brauchen? http.connect();wird POST senden, nicht wahr?
János
16
"Das Senden einer POST-Anfrage ist in Vanilla Java einfach." Und dann folgen Dutzende von Codezeilen im Vergleich zu requests.post('http://httpbin.org/post', data = {'key':'value'})Python… Ich bin neu in Java, daher ist dies eine sehr seltsame Verwendung des Wortes „einfach“ für mich :)
Lynn
1
Es ist relativ einfacher als ich erwartet hatte, wenn man bedenkt, dass es Java ist :)
Shaahiin
rätselhaft \ r \ n \ r \ n bedeutet CRLF CRLF (Wagenrücklauf + Zeilenvorschub). Es wird 2x neue Zeile erstellt. Die erste neue Zeile soll die aktuelle Zeile beenden. Die zweite Zeile dient zur Unterscheidung des http-Headers vom http-Body in einer Anforderung. HTTP ist ein ASCII-basiertes Protokoll. Dies ist die Regel zum Einfügen von \ r \ n.
Mitja Gustin
99
String rawData = "id=10";
String type = "application/x-www-form-urlencoded";
String encodedData = URLEncoder.encode( rawData, "UTF-8" ); 
URL u = new URL("http://www.example.com/page.php");
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty( "Content-Type", type );
conn.setRequestProperty( "Content-Length", String.valueOf(encodedData.length()));
OutputStream os = conn.getOutputStream();
os.write(encodedData.getBytes());
DuduAlul
quelle
Wichtig zu beachten: Die Verwendung von etwas anderem als String.getBytes () scheint nicht zu funktionieren. Beispielsweise schlägt die Verwendung eines PrintWriter völlig fehl.
Little Bobby Tables
5
und wie man 2 Postdaten setzt? Durch Doppelpunkt, Komma getrennt?
laute Katze
10
encode(String)ist veraltet. Sie müssen verwenden encode(String, String), was den Codierungstyp angibt. Beispiel : encode(rawData, "UTF-8").
Sudo
3
Vielleicht möchten Sie am Ende folgen. Dies würde sicherstellen, dass die Anforderung abgeschlossen ist und der Server die Möglichkeit erhält, die Antwort zu verarbeiten: conn.getResponseCode ();
Szymon Jachim
3
Codieren Sie nicht die gesamte Zeichenfolge. Sie müssen nur den Wert jedes Parameters codieren
user2914191
22

Die erste Antwort war großartig, aber ich musste try / catch hinzufügen, um Java-Compilerfehler zu vermeiden.
Außerdem hatte ich Probleme herauszufinden, wie man das liestHttpResponse mit Java-Bibliotheken .

Hier ist der vollständigere Code:

/*
 * Create the POST request
 */
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://example.com/");
// Request parameters and other properties.
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("user", "Bob"));
try {
    httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
} catch (UnsupportedEncodingException e) {
    // writing error to Log
    e.printStackTrace();
}
/*
 * Execute the HTTP Request
 */
try {
    HttpResponse response = httpClient.execute(httpPost);
    HttpEntity respEntity = response.getEntity();

    if (respEntity != null) {
        // EntityUtils to get the response content
        String content =  EntityUtils.toString(respEntity);
    }
} catch (ClientProtocolException e) {
    // writing exception to log
    e.printStackTrace();
} catch (IOException e) {
    // writing exception to log
    e.printStackTrace();
}
Mar Cnu
quelle
EntityUtils war hilfreich.
Jay
6
Entschuldigung, aber Sie haben keine Fehler festgestellt, sondern sie eingeführt. Das Abfangen von Ausnahmen an einem Ort, an dem Sie nicht damit umgehen können, ist einfach falsch und e.printStackTrace()behandelt nichts.
Maaartinus
java.net.ConnectException:
Zeitüberschreitung der
5

einfachste Möglichkeit, Parameter mit der Post-Anfrage zu senden:

String postURL = "http://www.example.com/page.php";

HttpPost post = new HttpPost(postURL);

List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("id", "10"));

UrlEncodedFormEntity ent = new UrlEncodedFormEntity(params, "UTF-8");
post.setEntity(ent);

HttpClient client = new DefaultHttpClient();
HttpResponse responsePOST = client.execute(post);

Du hast gemacht. Jetzt können Sie verwenden responsePOST. Antwortinhalt als Zeichenfolge abrufen:

BufferedReader reader = new BufferedReader(new  InputStreamReader(responsePOST.getEntity().getContent()), 2048);

if (responsePOST != null) {
    StringBuilder sb = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(" line : " + line);
        sb.append(line);
    }
    String getResponseString = "";
    getResponseString = sb.toString();
//use server output getResponseString as string value.
}
Chandan Kumar
quelle
1

Call HttpURLConnection.setRequestMethod("POST")and HttpURLConnection.setDoOutput(true);Eigentlich wird nur Letzteres benötigt, da POST dann zur Standardmethode wird.

Marquis von Lorne
quelle
it it HttpURLConnection.setRequestMethod () :)
Jose Diaz
1

Ich empfehle die Verwendung von http-request, die auf Apache http api basiert.

HttpRequest<String> httpRequest = HttpRequestBuilder.createPost("http://www.example.com/page.php", String.class)
.responseDeserializer(ResponseDeserializer.ignorableDeserializer()).build();

public void send(){
   String response = httpRequest.execute("id", "10").get();
}
Beno Arakelyan
quelle