Invio di una richiesta POST HTTP in Java


295

supponiamo che questo URL ...

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

(Qui l'id deve essere inviato in una richiesta POST)

Voglio inviare il id = 10al serverpage.php , che lo accetta in un metodo POST.

Come posso farlo da Java?

Ho provato questo:

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

Ma non riesco ancora a capire come inviarlo tramite POST

Risposte:


339

Risposta aggiornata:

Poiché alcune delle classi, nella risposta originale, sono obsolete nella versione più recente dei componenti HTTP di Apache, sto pubblicando questo aggiornamento.

A proposito, puoi accedere alla documentazione completa per ulteriori esempi qui .

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
    }
}

Risposta originale:

Consiglio di usare Apache HttpClient. è più veloce e più facile da implementare.

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.

per maggiori informazioni controlla questo url: http://hc.apache.org/


25
Dopo aver provato per un po 'a mettere le mani su PostMethod, sembra che ora sia chiamato HttpPostsecondo stackoverflow.com/a/9242394/1338936 - solo per chiunque trovi questa risposta come ho fatto io :)
Martin Lyne,

1
@Juan (e Martin Lyne) grazie per i commenti. Ho appena aggiornato la risposta.
mhshams,

La tua risposta rivista utilizza ancora hc.apache.org?
Djangofan,

@djangofan si. c'è un link ad apache-hc anche nella risposta rivista.
mhshams,

6
dovresti aggiungere le librerie importate
gouchaoer,

192

L'invio di una richiesta POST è semplice in Java vanilla. A partire da a URL, non è necessario convertirlo in un URLConnectionutilizzo url.openConnection();. Successivamente, dobbiamo eseguirne il cast in a HttpURLConnection, in modo da poter accedere al suo setRequestMethod()metodo per impostare il nostro metodo. Finalmente diciamo che invieremo i dati tramite la connessione.

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);

Dobbiamo quindi dichiarare ciò che invieremo:

Invio di un modulo semplice

Un normale POST proveniente da un modulo http ha un formato ben definito . Dobbiamo convertire il nostro input in questo formato:

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;

Possiamo quindi allegare i contenuti del nostro modulo alla richiesta http con le intestazioni appropriate e inviarlo.

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

Invio di JSON

Possiamo anche inviare json usando java, anche questo è facile:

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

Ricorda che server diversi accettano tipi di contenuto diversi per json, vedi questa domanda.


Invio di file con java post

L'invio di file può essere considerato più difficile da gestire in quanto il formato è più complesso. Aggiungeremo anche il supporto per l'invio dei file come stringa, poiché non vogliamo bufferizzare completamente il file nella memoria.

Per questo, definiamo alcuni metodi di supporto:

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));
}

Possiamo quindi utilizzare questi metodi per creare una richiesta di post multipart come segue:

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

5
Questo post è utile, ma piuttosto imperfetto. Mi ci sono voluti 2 giorni per farlo funzionare. Quindi per farlo funzionare devi sostituire StandartCharsets.UTF8 con StandardCharsets.UTF_8. boundaryBytes e finishBoundaryBytes devono ottenere due trattini aggiuntivi che NON vengono trasmessi nel Content-Type, quindi boundaryBytes = ("-" + boundary + "\ r \ n"). get ... Devi anche trasmettere i boundaryBytes una volta PRIMA che il primo campo o il primo campo vengano ignorati!
Algoman

Perché la out.write(finishBoundaryBytes);linea ha bisogno? http.connect();eseguirà l'invio POST, non è vero?
János,

17
"L'invio di una richiesta POST è semplice in Java vanilla." E poi seguono decine di righe di codice, rispetto a qualcosa come requests.post('http://httpbin.org/post', data = {'key':'value'})in Python ... Sono nuovo di Java, quindi questo è un uso molto strano della parola "facile" per me :)
Lynn,

1
È relativamente più facile di quanto mi aspettassi considerando Java :)
Shaahiin,

enigmatico \ r \ n \ r \ n significa CRLF CRLF (ritorno a capo + avanzamento riga). Crea 2x nuove linee. La prima nuova linea è di finire la linea corrente. La seconda riga consiste nel distinguere l'intestazione http dal corpo http in una richiesta. HTTP è un protocollo basato su ASCII. Questa è la regola per inserire \ 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());

Importante da notare: l'utilizzo di qualsiasi cosa diversa da String.getBytes () non sembra funzionare. Ad esempio, l'utilizzo di PrintWriter fallisce totalmente.
Tavolini Bobby il

5
e come impostare 2 dati post? Separato da due punti, virgola?
gatto rumoroso

10
encode(String)è deprecato. Devi usare encode(String, String), che specifica il tipo di codifica. Esempio: encode(rawData, "UTF-8").
sudo,

3
Potresti voler seguire alla fine. Ciò assicurerebbe che la richiesta sia terminata e che il server abbia la possibilità di elaborare la risposta: conn.getResponseCode ();
Szymon Jachim,

3
non codificare l'intera stringa .. devi codificare solo il valore di ciascun parametro
user2914191,

22

La prima risposta è stata fantastica, ma ho dovuto aggiungere try / catch per evitare errori del compilatore Java.
Inoltre, ho avuto problemi a capire come leggere ilHttpResponse librerie Java.

Ecco il codice più completo:

/*
 * 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();
}

EntityUtils è stato utile.
Jay,

6
Siamo spiacenti, ma non hai riscontrato errori, li hai introdotti. Catturare le eccezioni in un luogo in cui non è possibile gestirle è semplicemente sbagliato e e.printStackTrace()non gestisce nulla.
maaartinus,

java.net.ConnectException: Timeout connessione: connect
kerZy Hart


5

modo più semplice per inviare parametri con la richiesta di post:

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);

Hai fatto. ora puoi usare responsePOST. Ottieni contenuto di risposta come stringa:

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.
}

1

Chiama HttpURLConnection.setRequestMethod("POST")e in HttpURLConnection.setDoOutput(true);realtà è necessario solo quest'ultimo, poiché il POST diventa il metodo predefinito.


HttpURLConnection.setRequestMethod () :)
Jose Diaz,

1

Consiglio di utilizzare la richiesta http basata su apache http api.

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();
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.