viewprofile tutorial mkyong data java http httprequest httpurlconnection urlconnection

tutorial - java httpurlconnection send data



Cómo usar java.net.URLConnection para disparar y manejar solicitudes HTTP (11)

El uso de java.net.URLConnection se pregunta aquí con bastante frecuencia, y el tutorial de Oracle es demasiado conciso al respecto.

Básicamente, ese tutorial muestra cómo disparar una solicitud GET y leer la respuesta. No explica en ningún lugar cómo usarlo para, entre otras cosas, realizar una solicitud POST, establecer encabezados de solicitud, leer encabezados de respuesta, lidiar con cookies, enviar un formulario HTML, cargar un archivo, etc.

Entonces, ¿cómo puedo usar java.net.URLConnection para disparar y manejar solicitudes HTTP "avanzadas"?


Actualizar

El nuevo Cliente HTTP se distribuyó con Java 9 pero como parte de un módulo de Incubadora llamado jdk.incubator.httpclient . Los módulos de la incubadora son un medio para poner las API no definitivas en manos de los desarrolladores, mientras que las API avanzan hacia su finalización o eliminación en una versión futura.

En Java 9, puedes enviar una solicitud GET como:

// GET HttpResponse response = HttpRequest .create(new URI("http://www..com")) .headers("Foo", "foovalue", "Bar", "barvalue") .GET() .response();

Luego puede examinar el HttpResponse devuelto:

int statusCode = response.statusCode(); String responseBody = response.body(HttpResponse.asString());

Dado que este nuevo cliente HTTP está en java.httpclient jdk.incubator.httpclient módulo jdk.incubator.httpclient , debe declarar esta dependencia en su archivo module-info.java :

module com.foo.bar { requires jdk.incubator.httpclient; }


Cuando se trabaja con HTTP, casi siempre es más útil referirse a HttpURLConnection lugar de a la clase base URLConnection (ya que URLConnection es una clase abstracta cuando pides URLConnection.openConnection() en una URL HTTP, eso es lo que obtendrás de todos modos).

Luego, en lugar de confiar en URLConnection#setDoOutput(true) para establecer implícitamente el método de solicitud en POST, en lugar de hacerlo, haga httpURLConnection.setRequestMethod("POST") que algunos pueden encontrar más natural (y que también le permite especificar otros métodos de solicitud, como PONER , BORRAR , ...).

También proporciona constantes HTTP útiles para que puedas hacer:

int responseCode = httpURLConnection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) {


Esta respuesta también me inspiró mucho.

A menudo estoy en proyectos donde necesito hacer algo de HTTP, y es posible que no quiera incluir muchas dependencias de terceros (que traigan otros, etc., etc.)

Comencé a escribir mis propias utilidades basadas en parte de esta conversación (no en ninguna otra parte):

package org.boon.utils; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Map; import static org.boon.utils.IO.read; public class HTTP {

Entonces hay solo un montón o métodos estáticos.

public static String get( final String url) { Exceptions.tryIt(() -> { URLConnection connection; connection = doGet(url, null, null, null); return extractResponseString(connection); }); return null; } public static String getWithHeaders( final String url, final Map<String, ? extends Object> headers) { URLConnection connection; try { connection = doGet(url, headers, null, null); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String getWithContentType( final String url, final Map<String, ? extends Object> headers, String contentType) { URLConnection connection; try { connection = doGet(url, headers, contentType, null); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String getWithCharSet( final String url, final Map<String, ? extends Object> headers, String contentType, String charSet) { URLConnection connection; try { connection = doGet(url, headers, contentType, charSet); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } }

Luego publica ...

public static String postBody( final String url, final String body) { URLConnection connection; try { connection = doPost(url, null, "text/plain", null, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String postBodyWithHeaders( final String url, final Map<String, ? extends Object> headers, final String body) { URLConnection connection; try { connection = doPost(url, headers, "text/plain", null, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String postBodyWithContentType( final String url, final Map<String, ? extends Object> headers, final String contentType, final String body) { URLConnection connection; try { connection = doPost(url, headers, contentType, null, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } public static String postBodyWithCharset( final String url, final Map<String, ? extends Object> headers, final String contentType, final String charSet, final String body) { URLConnection connection; try { connection = doPost(url, headers, contentType, charSet, body); return extractResponseString(connection); } catch (Exception ex) { Exceptions.handle(ex); return null; } } private static URLConnection doPost(String url, Map<String, ? extends Object> headers, String contentType, String charset, String body ) throws IOException { URLConnection connection;/* Handle output. */ connection = new URL(url).openConnection(); connection.setDoOutput(true); manageContentTypeHeaders(contentType, charset, connection); manageHeaders(headers, connection); IO.write(connection.getOutputStream(), body, IO.CHARSET); return connection; } private static void manageHeaders(Map<String, ? extends Object> headers, URLConnection connection) { if (headers != null) { for (Map.Entry<String, ? extends Object> entry : headers.entrySet()) { connection.setRequestProperty(entry.getKey(), entry.getValue().toString()); } } } private static void manageContentTypeHeaders(String contentType, String charset, URLConnection connection) { connection.setRequestProperty("Accept-Charset", charset == null ? IO.CHARSET : charset); if (contentType!=null && !contentType.isEmpty()) { connection.setRequestProperty("Content-Type", contentType); } } private static URLConnection doGet(String url, Map<String, ? extends Object> headers, String contentType, String charset) throws IOException { URLConnection connection;/* Handle output. */ connection = new URL(url).openConnection(); manageContentTypeHeaders(contentType, charset, connection); manageHeaders(headers, connection); return connection; } private static String extractResponseString(URLConnection connection) throws IOException { /* Handle input. */ HttpURLConnection http = (HttpURLConnection)connection; int status = http.getResponseCode(); String charset = getCharset(connection.getHeaderField("Content-Type")); if (status==200) { return readResponseBody(http, charset); } else { return readErrorResponseBody(http, status, charset); } } private static String readErrorResponseBody(HttpURLConnection http, int status, String charset) { InputStream errorStream = http.getErrorStream(); if ( errorStream!=null ) { String error = charset== null ? read( errorStream ) : read( errorStream, charset ); throw new RuntimeException("STATUS CODE =" + status + "/n/n" + error); } else { throw new RuntimeException("STATUS CODE =" + status); } } private static String readResponseBody(HttpURLConnection http, String charset) throws IOException { if (charset != null) { return read(http.getInputStream(), charset); } else { return read(http.getInputStream()); } } private static String getCharset(String contentType) { if (contentType==null) { return null; } String charset = null; for (String param : contentType.replace(" ", "").split(";")) { if (param.startsWith("charset=")) { charset = param.split("=", 2)[1]; break; } } charset = charset == null ? IO.CHARSET : charset; return charset; }

Bueno, ya captas la idea....

Aquí están las pruebas:

static class MyHandler implements HttpHandler { public void handle(HttpExchange t) throws IOException { InputStream requestBody = t.getRequestBody(); String body = IO.read(requestBody); Headers requestHeaders = t.getRequestHeaders(); body = body + "/n" + copy(requestHeaders).toString(); t.sendResponseHeaders(200, body.length()); OutputStream os = t.getResponseBody(); os.write(body.getBytes()); os.close(); } } @Test public void testHappy() throws Exception { HttpServer server = HttpServer.create(new InetSocketAddress(9212), 0); server.createContext("/test", new MyHandler()); server.setExecutor(null); // creates a default executor server.start(); Thread.sleep(10); Map<String,String> headers = map("foo", "bar", "fun", "sun"); String response = HTTP.postBodyWithContentType("http://localhost:9212/test", headers, "text/plain", "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.postBodyWithCharset("http://localhost:9212/test", headers, "text/plain", "UTF-8", "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.postBodyWithHeaders("http://localhost:9212/test", headers, "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.get("http://localhost:9212/test"); System.out.println(response); response = HTTP.getWithHeaders("http://localhost:9212/test", headers); System.out.println(response); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.getWithContentType("http://localhost:9212/test", headers, "text/plain"); System.out.println(response); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); response = HTTP.getWithCharSet("http://localhost:9212/test", headers, "text/plain", "UTF-8"); System.out.println(response); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); Thread.sleep(10); server.stop(0); } @Test public void testPostBody() throws Exception { HttpServer server = HttpServer.create(new InetSocketAddress(9220), 0); server.createContext("/test", new MyHandler()); server.setExecutor(null); // creates a default executor server.start(); Thread.sleep(10); Map<String,String> headers = map("foo", "bar", "fun", "sun"); String response = HTTP.postBody("http://localhost:9220/test", "hi mom"); assertTrue(response.contains("hi mom")); Thread.sleep(10); server.stop(0); } @Test(expected = RuntimeException.class) public void testSad() throws Exception { HttpServer server = HttpServer.create(new InetSocketAddress(9213), 0); server.createContext("/test", new MyHandler()); server.setExecutor(null); // creates a default executor server.start(); Thread.sleep(10); Map<String,String> headers = map("foo", "bar", "fun", "sun"); String response = HTTP.postBodyWithContentType("http://localhost:9213/foo", headers, "text/plain", "hi mom"); System.out.println(response); assertTrue(response.contains("hi mom")); assertTrue(response.contains("Fun=[sun], Foo=[bar]")); Thread.sleep(10); server.stop(0); }

Puedes encontrar el resto aqui:

https://github.com/RichardHightower/boon

Mi objetivo es proporcionar las cosas comunes que uno querría hacer de una manera un poco más fácil que ...


Hay 2 opciones a las que puedes ir con Hits de URL HTTP: GET / POST

Solicitud GET: -

HttpURLConnection.setFollowRedirects(true); // defaults to true String url = "https://name_of_the_url"; URL request_url = new URL(url); HttpURLConnection http_conn = (HttpURLConnection)request_url.openConnection(); http_conn.setConnectTimeout(100000); http_conn.setReadTimeout(100000); http_conn.setInstanceFollowRedirects(true); System.out.println(String.valueOf(http_conn.getResponseCode()));

Solicitud POST: -

HttpURLConnection.setFollowRedirects(true); // defaults to true String url = "https://name_of_the_url" URL request_url = new URL(url); HttpURLConnection http_conn = (HttpURLConnection)request_url.openConnection(); http_conn.setConnectTimeout(100000); http_conn.setReadTimeout(100000); http_conn.setInstanceFollowRedirects(true); http_conn.setDoOutput(true); PrintWriter out = new PrintWriter(http_conn.getOutputStream()); if (urlparameter != null) { out.println(urlparameter); } out.close(); out = null; System.out.println(String.valueOf(http_conn.getResponseCode()));


Inicialmente, fui engañado por este article que favorece a HttpClient .

Más tarde me di cuenta de que HttpURLConnection se mantendrá en este article

Según el blog de Google :

El cliente HTTP de Apache tiene menos errores en Eclair y Froyo. Es la mejor opción para estos lanzamientos. Para Gingerbread, HttpURLConnection es la mejor opción. Su API simple y su pequeño tamaño lo hacen ideal para Android.

La compresión transparente y el almacenamiento en caché de respuestas reducen el uso de la red, mejoran la velocidad y ahorran batería. Las nuevas aplicaciones deben usar HttpURLConnection; Es donde gastaremos nuestra energía en el futuro.

Después de leer rapidvaluesolutions.com/tech_blog/… y algunas otras preguntas sobre el flujo, estoy convencido de que HttpURLConnection va a permanecer por más tiempo.

Algunas de las preguntas de la SE que favorecen las HttpURLConnections :

En Android, realice una solicitud POST con datos de formulario codificado de URL sin utilizar UrlEncodedFormEntity

HttpPost funciona en un proyecto Java, no en Android



Le sugiero que eche un vistazo al código en kevinsawicki/http-request , es básicamente un envoltorio encima de HttpUrlConnection que proporciona una API mucho más simple en caso de que solo quiera realizar las solicitudes en este momento o puede echar un vistazo a las fuentes (no es demasiado grande) para ver cómo se manejan las conexiones.

Ejemplo: realice una solicitud GET con la application/json tipo de contenido application/json y algunos parámetros de consulta:

// GET http://google.com?q=baseball%20gloves&size=100 String response = HttpRequest.get("http://google.com", true, "q", "baseball gloves", "size", 100) .accept("application/json") .body(); System.out.println("Response was: " + response);


También está OkHttp , que es un cliente HTTP que es eficiente por defecto:

  • La compatibilidad con HTTP / 2 permite que todas las solicitudes al mismo host compartan un socket.
  • La agrupación de conexiones reduce la latencia de la solicitud (si HTTP / 2 no está disponible).
  • GZIP transparente reduce los tamaños de descarga.
  • El almacenamiento en caché de respuestas evita la red completamente para las solicitudes de repetición.

Primero crea una instancia de OkHttpClient :

OkHttpClient client = new OkHttpClient();

Luego, prepara tu solicitud GET :

Request request = new Request.Builder() .url(url) .build();

Por último, utilizar OkHttpClientpara enviar preparados Request:

Response response = client.newCall(request).execute();

Para más detalles, puedes consultar la documentación de OkHttp.


También puede usar JdkRequest desde jcabi-http (soy un desarrollador), que hace todo este trabajo por usted, decorando HttpURLConnection, disparando solicitudes HTTP y analizando respuestas, por ejemplo:

String html = new JdkRequest("http://www.google.com").fetch().body();

Consulte esta publicación del blog para obtener más información: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html


Primero un descargo de responsabilidad de antemano: los fragmentos de código publicados son todos ejemplos básicos. Tendrá que manejar las IOException triviales y las RuntimeException como NullPointerException , ArrayIndexOutOfBoundsException y consortes usted mismo.

Preparando

Primero necesitamos saber al menos la URL y el conjunto de caracteres. Los parámetros son opcionales y dependen de los requisitos funcionales.

String url = "http://example.com"; String charset = "UTF-8"; // Or in Java 7 and later, use the constant: java.nio.charset.StandardCharsets.UTF_8.name() String param1 = "value1"; String param2 = "value2"; // ... String query = String.format("param1=%s&param2=%s", URLEncoder.encode(param1, charset), URLEncoder.encode(param2, charset));

Los parámetros de consulta deben estar en formato name=value y deben estar concatenados por & . Normalmente, también URL-encode la URL-encode los parámetros de consulta con el conjunto de caracteres especificado utilizando URLEncoder#encode() .

El String#format() es solo por conveniencia. Prefiero cuando necesito al operador de concatenación de cadenas más de dos veces.

Activar una solicitud HTTP GET con (opcionalmente) parámetros de consulta

Es una tarea trivial. Es el método de solicitud predeterminado.

URLConnection connection = new URL(url + "?" + query).openConnection(); connection.setRequestProperty("Accept-Charset", charset); InputStream response = connection.getInputStream(); // ...

Cualquier cadena de consulta debe ser concatenada a la URL usando ? . El encabezado Accept-Charset puede indicar al servidor en qué codificación están los parámetros. Si no envía ninguna cadena de consulta, puede dejar el encabezado Accept-Charset . Si no necesita configurar ningún encabezado, incluso puede usar el método de acceso directo URL#openStream() .

InputStream response = new URL(url).openStream(); // ...

De cualquier manera, si el otro lado es un HttpServlet , entonces se doGet() su método doGet() y los parámetros estarán disponibles por HttpServletRequest#getParameter() .

Para fines de prueba, puede imprimir el cuerpo de la respuesta a la salida estándar de la siguiente manera:

try (Scanner scanner = new Scanner(response)) { String responseBody = scanner.useDelimiter("//A").next(); System.out.println(responseBody); }

Activar una solicitud HTTP POST con parámetros de consulta

Al establecer URLConnection#setDoOutput() en true establece implícitamente el método de solicitud en POST. El HTTP POST estándar como lo hacen los formularios web es de tipo application/x-www-form-urlencoded donde la cadena de consulta se escribe en el cuerpo de la solicitud.

URLConnection connection = new URL(url).openConnection(); connection.setDoOutput(true); // Triggers POST. connection.setRequestProperty("Accept-Charset", charset); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset); try (OutputStream output = connection.getOutputStream()) { output.write(query.getBytes(charset)); } InputStream response = connection.getInputStream(); // ...

Nota: siempre que desee enviar un formulario HTML mediante programación, no olvide llevar los pares name=value de cualquier elemento <input type="hidden"> a la cadena de consulta y, por supuesto, también el par name=value de el elemento <input type="submit"> que le gustaría "presionar" programáticamente (porque generalmente se usa en el lado del servidor para distinguir si se presionó un botón y, de ser así, cuál).

También puede emitir el java.net.URLConnection obtenido a HttpURLConnection y usar su HttpURLConnection#setRequestMethod() lugar. Pero si está tratando de usar la conexión para la salida, todavía necesita establecer URLConnection#setDoOutput() en true .

HttpURLConnection httpConnection = (HttpURLConnection) new URL(url).openConnection(); httpConnection.setRequestMethod("POST"); // ...

De cualquier manera, si el otro lado es un HttpServlet , entonces se doPost() su método doPost() y los parámetros estarán disponibles por HttpServletRequest#getParameter() .

En realidad disparando la solicitud HTTP

Puede activar la solicitud HTTP explícitamente con URLConnection#connect() , pero la solicitud se activará automáticamente a petición cuando desee obtener información sobre la respuesta HTTP, como el cuerpo de la respuesta que usa URLConnection#getInputStream() y así sucesivamente. Los ejemplos anteriores hacen exactamente eso, por lo que la llamada connect() es de hecho superflua.

Recopilación de información de respuesta HTTP

  1. Estado de respuesta HTTP :

    Necesitas una HttpURLConnection aquí. Echalo primero si es necesario.

    int status = httpConnection.getResponseCode();

  2. Cabeceras de respuesta HTTP :

    for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) { System.out.println(header.getKey() + "=" + header.getValue()); }

  3. Codificación de respuesta HTTP :

    Cuando Content-Type contiene un parámetro charset , entonces el cuerpo de la respuesta probablemente esté basado en texto y nos gustaría procesar el cuerpo de la respuesta con la codificación de caracteres especificada del lado del servidor.

    String contentType = connection.getHeaderField("Content-Type"); String charset = null; for (String param : contentType.replace(" ", "").split(";")) { if (param.startsWith("charset=")) { charset = param.split("=", 2)[1]; break; } } if (charset != null) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(response, charset))) { for (String line; (line = reader.readLine()) != null;) { // ... System.out.println(line) ? } } } else { // It''s likely binary content, use InputStream/OutputStream. }

Mantener la sesión

La sesión del lado del servidor suele estar respaldada por una cookie. Algunos formularios web requieren que haya iniciado sesión y / o sea seguido por una sesión. Puede utilizar la API de CookieHandler para mantener las cookies. CookiePolicy preparar un CookieManager con una CookiePolicy de ACCEPT_ALL antes de enviar todas las solicitudes HTTP.

// First set the default cookie manager. CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL)); // All the following subsequent URLConnections will use the same cookie manager. URLConnection connection = new URL(url).openConnection(); // ... connection = new URL(url).openConnection(); // ... connection = new URL(url).openConnection(); // ...

Tenga en cuenta que se sabe que esto no siempre funciona correctamente en todas las circunstancias. Si falla para usted, lo mejor es reunir y configurar manualmente los encabezados de las cookies. Básicamente, debe capturar todos Set-Cookie encabezados Set-Cookie de la respuesta del inicio de sesión o la primera solicitud GET y luego pasar esto a través de las solicitudes posteriores.

// Gather all cookies on the first request. URLConnection connection = new URL(url).openConnection(); List<String> cookies = connection.getHeaderFields().get("Set-Cookie"); // ... // Then use the same cookies on all subsequent requests. connection = new URL(url).openConnection(); for (String cookie : cookies) { connection.addRequestProperty("Cookie", cookie.split(";", 2)[0]); } // ...

La split(";", 2)[0] está ahí para deshacerse de los atributos de las cookies que son irrelevantes para el lado del servidor, como expires , path , etc. Alternativamente, también puede usar cookie.substring(0, cookie.indexOf('';'')) lugar de split() .

Modo de streaming

La HttpURLConnection almacenará de forma predeterminada todo el cuerpo de la solicitud antes de enviarla, independientemente de si ha establecido una longitud de contenido fija utilizando connection.setRequestProperty("Content-Length", contentLength); . Esto puede causar OutOfMemoryException siempre que envíe simultáneamente solicitudes POST de gran tamaño (por ejemplo, subir archivos). Para evitar esto, le gustaría configurar HttpURLConnection#setFixedLengthStreamingMode() .

httpConnection.setFixedLengthStreamingMode(contentLength);

Pero si la longitud del contenido no se conoce de antemano, entonces puede utilizar el modo de transmisión fragmentada configurando HttpURLConnection#setChunkedStreamingMode() consecuencia. Esto establecerá el encabezado de Transfer-Encoding HTTP en chunked lo que forzará el envío del cuerpo de la solicitud en trozos. El siguiente ejemplo enviará el cuerpo en trozos de 1KB.

httpConnection.setChunkedStreamingMode(1024);

Agente de usuario

Puede suceder que una solicitud devuelva una respuesta inesperada, mientras funciona bien con un navegador web real . El lado del servidor probablemente está bloqueando las solicitudes basadas en el encabezado de solicitud de User-Agent . Por URLConnection , el URLConnection lo establecerá en Java/1.6.0_19 donde la última parte es obviamente la versión JRE. Puede anular esto de la siguiente manera:

connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"); // Do as if you''re using Chrome 41 on Windows 7.

Utilice la cadena User-Agent de un navegador reciente .

Manejo de errores

Si el código de respuesta HTTP es 4nn (Error de cliente) o 5nn (Error de servidor), es posible que desee leer HttpURLConnection#getErrorStream() para ver si el servidor ha enviado información de error útil.

InputStream error = ((HttpURLConnection) connection).getErrorStream();

Si el código de respuesta HTTP es -1, entonces algo salió mal con el manejo de la conexión y la respuesta. La implementación de HttpURLConnection encuentra en JRE más antiguos con un poco de error para mantener vivas las conexiones. Es posible que desee desactivarlo configurando la propiedad del sistema http.keepAlive en false . Puede hacerlo mediante programación al comienzo de su aplicación de la siguiente manera:

System.setProperty("http.keepAlive", "false");

Subiendo archivos

Normalmente usaría multipart/form-data codificación multipart/form-data para contenido POST mixto (datos binarios y de caracteres). La codificación se describe con más detalle en RFC2388 .

String param = "value"; File textFile = new File("/path/to/file.txt"); File binaryFile = new File("/path/to/file.bin"); String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value. String CRLF = "/r/n"; // Line separator required by multipart/form-data. URLConnection connection = new URL(url).openConnection(); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); try ( OutputStream output = connection.getOutputStream(); PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true); ) { // Send normal param. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=/"param/"").append(CRLF); writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); writer.append(CRLF).append(param).append(CRLF).flush(); // Send text file. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=/"textFile/"; filename=/"" + textFile.getName() + "/"").append(CRLF); writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); // Text file itself must be saved in this charset! writer.append(CRLF).flush(); Files.copy(textFile.toPath(), output); output.flush(); // Important before continuing with writer! writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary. // Send binary file. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=/"binaryFile/"; filename=/"" + binaryFile.getName() + "/"").append(CRLF); writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(binaryFile.getName())).append(CRLF); writer.append("Content-Transfer-Encoding: binary").append(CRLF); writer.append(CRLF).flush(); Files.copy(binaryFile.toPath(), output); output.flush(); // Important before continuing with writer! writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary. // End of multipart/form-data. writer.append("--" + boundary + "--").append(CRLF).flush(); }

Si el otro lado es un HttpServlet , entonces se doPost() su método doPost() y las partes estarán disponibles por HttpServletRequest#getPart() (nota, por lo tanto, no getParameter() y así sucesivamente!). El método getPart() es sin embargo relativamente nuevo, se introdujo en Servlet 3.0 (Glassfish 3, Tomcat 7, etc.). Antes de Servlet 3.0, su mejor opción es usar Apache Commons FileUpload para analizar una solicitud multipart/form-data . También vea esta respuesta para ver ejemplos de los enfoques de FileUpload y Servelt 3.0.

Tratar con sitios HTTPS no confiables o mal configurados

A veces necesitas conectar una URL de HTTPS, tal vez porque estás escribiendo un raspador web. En ese caso, es probable que se enfrente a una javax.net.ssl.SSLException: Not trusted server certificate en algunos sitios HTTPS que no mantiene sus certificados SSL actualizados, o una java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found o javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name en algunos sitios HTTPS mal configurados.

El siguiente inicializador static ejecuta una sola vez en su clase de raspador web debería hacer que HttpsURLConnection más indulgente con respecto a esos sitios HTTPS y, por lo tanto, no debe lanzar esas excepciones.

static { TrustManager[] trustAllCertificates = new TrustManager[] { new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; // Not relevant. } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { // Do nothing. Just allow them all. } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { // Do nothing. Just allow them all. } } }; HostnameVerifier trustAllHostnames = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; // Just allow them all. } }; try { System.setProperty("jsse.enableSNIExtension", "false"); SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCertificates, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier(trustAllHostnames); } catch (GeneralSecurityException e) { throw new ExceptionInInitializerError(e); } }

Ultimas palabras

El HttpComponents HttpClient de Apache es mucho más conveniente en todo esto :)

Análisis y extracción de HTML.

Si todo lo que desea es analizar y extraer datos de HTML, utilice un analizador HTML como Jsoup.


Si está utilizando http, por favor elimine esta línea.

urlConnection.setDoOutput(true);