Envoi d'une requête HTTP POST en Java


295

supposons cette URL ...

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

(Ici, l'identifiant doit être envoyé dans une demande POST)

Je veux envoyer le id = 10au serveur page.php, qui l'accepte dans une méthode POST.

Comment faire cela depuis Java?

J'ai essayé ceci:

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

Mais je n'arrive toujours pas à comprendre comment l'envoyer via POST

Réponses:


339

Réponse mise à jour:

Étant donné que certaines classes, dans la réponse d'origine, sont obsolètes dans la nouvelle version des composants HTTP Apache, je publie cette mise à jour.

À propos, vous pouvez accéder à la documentation complète pour plus d'exemples ici .

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

Réponse originale:

Je recommande d'utiliser Apache HttpClient. son plus rapide et plus facile à mettre en œuvre.

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.

pour plus d'informations, consultez cette URL: http://hc.apache.org/


25
Après avoir essayé pendant un certain temps de mettre la main dessus, PostMethodil semble que ce soit désormais appelé HttpPostselon stackoverflow.com/a/9242394/1338936 - juste pour quiconque trouve cette réponse comme je l'ai fait :)
Martin Lyne

1
@Juan (et Martin Lyne) merci pour les commentaires. Je viens de mettre à jour la réponse.
mhshams

Votre réponse révisée utilise-t-elle toujours hc.apache.org?
djangofan

@djangofan oui. il y a aussi un lien vers apache-hc dans la réponse révisée.
mhshams le

6
vous devez ajouter les
bibliothèques

192

L'envoi d'une requête POST est facile en Java vanille. En commençant par un URL, nous avons besoin de t convertir en un URLConnectionutilisant url.openConnection();. Après cela, nous devons le convertir en un HttpURLConnection, afin que nous puissions accéder à sa setRequestMethod()méthode pour définir notre méthode. Nous disons enfin que nous allons envoyer des données via la connexion.

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

Nous devons ensuite indiquer ce que nous allons envoyer:

Envoi d'un formulaire simple

Un POST normal provenant d'un formulaire http a un format bien défini . Nous devons convertir notre entrée dans ce format:

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;

Nous pouvons ensuite joindre le contenu de notre formulaire à la demande http avec les en-têtes appropriés et l'envoyer.

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

Envoi de JSON

Nous pouvons également envoyer json en utilisant java, c'est aussi simple:

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

N'oubliez pas que différents serveurs acceptent différents types de contenu pour json, voir cette question.


Envoi de fichiers avec Java Post

L'envoi de fichiers peut être considéré comme plus difficile à gérer car le format est plus complexe. Nous allons également ajouter la prise en charge de l'envoi des fichiers sous forme de chaîne, car nous ne voulons pas mettre le fichier entièrement en mémoire tampon.

Pour cela, nous définissons quelques méthodes d'assistance:

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

Nous pouvons ensuite utiliser ces méthodes pour créer une demande de publication en plusieurs parties comme suit:

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
Ce message est utile, mais assez imparfait. Il m'a fallu 2 jours pour le faire fonctionner. Donc, pour le faire fonctionner, vous devez remplacer StandartCharsets.UTF8 par StandardCharsets.UTF_8. borderBytes et finishBoundaryBytes doivent obtenir deux tirets supplémentaires qui NE SONT PAS transmis dans le Content-Type, donc borderBytes = ("-" + bound + "\ r \ n"). get ... Vous devez également transmettre les boundBytes une fois AVANT le premier champ ou le premier champ sera ignoré!
Algoman

Pourquoi out.write(finishBoundaryBytes);ligne besoin? http.connect();va effectuer l'envoi POST, n'est-ce pas?
János

17
«L'envoi d'une demande POST est facile en Java vanilla.» Et puis des dizaines de lignes de code suivent, par rapport à quelque chose comme requests.post('http://httpbin.org/post', data = {'key':'value'})en Python… Je suis nouveau sur Java, donc c'est une utilisation très étrange du mot «facile» pour moi :)
Lynn

1
C'est relativement plus facile que ce à quoi je m'attendais étant donné que c'est Java :)
shaahiin

énigmatique \ r \ n \ r \ n signifie CRLF CRLF (retour chariot + saut de ligne). Il crée 2x nouvelle ligne. La première nouvelle ligne est de terminer la ligne actuelle. La deuxième ligne consiste à distinguer l'en-tête http du corps http dans une demande. HTTP est un protocole basé sur ASCII. Ceci est la règle d'insertion de \ 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());

Important à noter: utiliser autre chose que String.getBytes () ne semble pas fonctionner. Par exemple, l'utilisation d'un PrintWriter échoue totalement.
Little Bobby Tables

5
et comment définir 2 données de publication? Séparé par deux points, virgule?
chat bruyant

10
encode(String)est obsolète. Vous devez utiliser encode(String, String), qui spécifie le type d'encodage. Exemple: encode(rawData, "UTF-8").
sudo

3
Vous voudrez peut-être suivre à la fin. Cela garantirait que la demande est terminée et que le serveur a la possibilité de traiter la réponse: conn.getResponseCode ();
Szymon Jachim

3
ne pas encoder la chaîne entière .. vous devez encoder juste la valeur de chaque paramètre
user2914191

22

La première réponse a été excellente, mais j'ai dû ajouter try / catch pour éviter les erreurs du compilateur Java.
De plus, j'ai eu du mal à comprendre comment lire HttpResponseavec les bibliothèques Java.

Voici le code le plus complet:

/*
 * 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 était utile.
Jay

6
Désolé, mais vous n'avez détecté aucune erreur, vous les avez introduites. Attraper des exceptions dans un endroit où vous ne pouvez pas les gérer est tout à fait faux et e.printStackTrace()ne gère rien.
maaartinus

java.net.ConnectException: La connexion a expiré: connect
kerZy Hart


5

moyen le plus simple d'envoyer des paramètres avec la demande de publication:

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

Vous avez fait. vous pouvez maintenant utiliser responsePOST. Obtenez le contenu de la réponse sous forme de chaîne:

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

Appelez HttpURLConnection.setRequestMethod("POST")et en HttpURLConnection.setDoOutput(true);fait, seul ce dernier est nécessaire car POST devient alors la méthode par défaut.


it it HttpURLConnection.setRequestMethod () :)
Jose Diaz

1

Je recommande d'utiliser http-request basé sur 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();
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.