Отправка HTTP POST-запроса в Java

295

давайте предположим, что этот URL ...

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

(Здесь идентификатор должен быть отправлен в запросе POST)

Я хочу отправить на id = 10сервер page.php, который принимает его в метод POST.

Как я могу сделать это из Java?

Я попробовал это:

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

Но я все еще не могу понять, как отправить его через POST

Джаз
источник

Ответы:

339

Обновленный ответ:

Поскольку некоторые классы в первоначальном ответе устарели в новой версии HTTP-компонентов Apache, я публикую это обновление.

Кстати, вы можете получить доступ к полной документации для большего количества примеров здесь .

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

Оригинальный ответ:

Я рекомендую использовать Apache HttpClient. это быстрее и проще в реализации.

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.

для получения дополнительной информации проверьте этот URL: http://hc.apache.org/

mhshams
источник
25
После некоторой попытки заполучить PostMethodего, кажется, его теперь фактически называют HttpPostсогласно stackoverflow.com/a/9242394/1338936 - просто для любого, кто найдет этот ответ, как я :)
Martin Lyne
1
@Juan (и Мартин Лайн) спасибо за комментарии. Я только что обновил ответ.
mhshams
Ваш пересмотренный ответ все еще использует hc.apache.org?
Джангофан
@djangofan да. в пересмотренном ответе также есть ссылка на apache-hc.
mhshams
6
Вы должны добавить импортированные
библиотеки
192

Отправлять POST-запрос легко в ванильной Java. Начиная с a URL, нам нужно преобразовать его в URLConnectionиспользование url.openConnection();. После этого нам нужно привести его к a HttpURLConnection, чтобы мы могли получить доступ к его setRequestMethod()методу для установки нашего метода. Наконец, мы говорим, что собираемся отправлять данные через соединение.

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

Затем нам нужно указать, что мы собираемся отправить:

Отправка простой формы

Обычный POST из формы http имеет четко определенный формат. Нам нужно преобразовать наши данные в этот формат:

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;

Затем мы можем прикрепить содержимое нашей формы к http-запросу с соответствующими заголовками и отправить его.

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

Мы также можем отправить JSON с помощью Java, это также легко:

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

Помните, что разные серверы принимают разные типы контента для json, см. Этот вопрос.


Отправка файлов с помощью сообщения Java

Отправка файлов может считаться более сложной для обработки, поскольку формат является более сложным. Мы также собираемся добавить поддержку отправки файлов в виде строки, поскольку мы не хотим полностью буферизовать файл в памяти.

Для этого мы определим несколько вспомогательных методов:

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

Затем мы можем использовать эти методы для создания многочастного почтового запроса следующим образом:

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
источник
5
Этот пост полезен, но довольно некорректен. Мне потребовалось 2 дня, чтобы все заработало. Поэтому, чтобы заставить его работать, вы должны заменить StandartCharsets.UTF8 на StandardCharsets.UTF_8. borderBytes и finishBoundaryBytes должны получить два дополнительных дефиса, которые НЕ передаются в Content-Type, поэтому borderBytes = ("-" + border + "\ r \ n"). get ... Вам также необходимо один раз передать borderBytes ПЕРЕД первым полем или первым полем будет проигнорировано!
Algoman
Зачем out.write(finishBoundaryBytes);черта нужна?http.connect();будет выполнять отправку POST, не так ли?
Янош
17
«Отправлять POST-запрос легко в ванильной Java». А затем следуют десятки строк кода, по сравнению с чем-то вроде requests.post('http://httpbin.org/post', data = {'key':'value'})Python… Я новичок в Java, поэтому это очень странное использование слова «легко» для меня :)
Линн
1
Это относительно проще, чем я ожидал, учитывая, что это Java :)
shaahiin
Загадочный \ r \ n \ r \ n означает CRLF CRLF (возврат каретки + перевод строки). Создает 2x новую строку. Первая новая строка должна закончить текущую строку. Вторая строка должна отличать заголовок http от тела http в запросе. HTTP является протоколом на основе ASCII. Это правило для вставки \ r \ n.
Митя Густин
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
источник
Важно отметить: использование чего-либо, кроме String.getBytes (), похоже, не работает. Например, использование PrintWriter полностью не удается.
Маленькие столики Бобби
5
а как установить 2 поста данных? Разделяйте двоеточием, запятая?
шумный кот
10
encode(String)устарела. Вы должны использовать encode(String, String), который указывает тип кодировки. Пример: encode(rawData, "UTF-8").
Судо
3
Вы можете следовать в конце. Это позволит убедиться, что запрос завершен, и сервер получит возможность обработать ответ: conn.getResponseCode ();
Шимон Яхим,
3
не кодировать всю строку .. вы должны кодировать только значение каждого параметра
user2914191
22

Первый ответ был отличным, но мне пришлось добавить try / catch, чтобы избежать ошибок компилятора Java.
Кроме того, мне было трудно понять, как читать HttpResponseбиблиотеки Java.

Вот более полный код:

/*
 * 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 был полезен.
Джей
6
Извините, но вы не уловили ошибок, вы их ввели. Поймать исключения в месте, где вы не можете их обработать, совершенно неправильно и e.printStackTrace()ничего не обрабатывает.
Maaartinus
java.net.ConnectException:
Тайм-
17

Простой способ использования Apache HTTP Components:

Request.Post("http://www.example.com/page.php")
            .bodyForm(Form.form().add("id", "10").build())
            .execute()
            .returnContent();

Взгляните на свободный API

Матиас Бак
источник
3
Просто для удобства; Настройка зависимостей / информация: hc.apache.org/httpcomponents-client-4.5.x/httpclient/… и hc.apache.org/httpcomponents-client-4.5.x/fluent-hc/…
Ярослав Заруба,
5

Простейший способ отправки параметров с помощью почтового запроса:

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

Ты сделал. Теперь вы можете использовать responsePOST. Получить содержимое ответа в виде строки:

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

Вызовите HttpURLConnection.setRequestMethod("POST")и HttpURLConnection.setDoOutput(true);фактически только последний необходим, поскольку POST тогда становится методом по умолчанию.

Маркиз Лорн
источник
it it HttpURLConnection.setRequestMethod () :)
Хосе Диас
1

Я рекомендую использовать http-запрос, основанный на 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();
}
Бено Аракелян
источник