¿Cómo puedo hacer una solicitud POST multipart / form-data usando Java?

En los días de la versión 3.x de Apache Commons HttpClient, era posible realizar una solicitud POST multipart / form-data ( un ejemplo de 2004 ). Desafortunadamente, esto ya no es posible en la versión 4.0 de HttpClient .

Para nuestra actividad principal “HTTP”, multiparte está algo fuera de scope. Nos encantaría utilizar código multiparte mantenido por algún otro proyecto para el cual esté dentro del scope, pero no conozco ninguno. Intentamos mover el código multiparte a commons-codec hace algunos años, pero no despegué allí. Oleg recientemente mencionó otro proyecto que tiene código de análisis multiparte y podría estar interesado en nuestro código de formato multiparte. No sé el estado actual de eso. ( http://www.nabble.com/multipart-form-data-in-4.0-td14224819.html )

¿Alguien conoce alguna biblioteca Java que me permita escribir un cliente HTTP que pueda hacer una solicitud POST multipart / form-data?

Antecedentes: quiero usar la API remota de Zoho Writer .

    Usamos HttpClient 4.x para hacer una publicación de archivos de varias partes.

    ACTUALIZACIÓN : A partir de HttpClient 4.3 , algunas clases han quedado obsoletas. Aquí está el código con la nueva API:

    CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost uploadFile = new HttpPost("..."); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addTextBody("field1", "yes", ContentType.TEXT_PLAIN); // This attaches the file to the POST: File f = new File("[/path/to/upload]"); builder.addBinaryBody( "file", new FileInputStream(f), ContentType.APPLICATION_OCTET_STREAM, f.getName() ); HttpEntity multipart = builder.build(); uploadFile.setEntity(multipart); CloseableHttpResponse response = httpClient.execute(uploadFile); HttpEntity responseEntity = response.getEntity(); 

    A continuación se muestra el fragmento de código original con la API de HttpClient 4.0 en desuso :

     HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(url); FileBody bin = new FileBody(new File(fileName)); StringBody comment = new StringBody("Filename: " + fileName); MultipartEntity reqEntity = new MultipartEntity(); reqEntity.addPart("bin", bin); reqEntity.addPart("comment", comment); httppost.setEntity(reqEntity); HttpResponse response = httpclient.execute(httppost); HttpEntity resEntity = response.getEntity(); 

    Estas son las dependencias de Maven que tengo.

    Código de Java:

     HttpClient httpclient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(url); FileBody uploadFilePart = new FileBody(uploadFile); MultipartEntity reqEntity = new MultipartEntity(); reqEntity.addPart("upload-file", uploadFilePart); httpPost.setEntity(reqEntity); HttpResponse response = httpclient.execute(httpPost); 

    Dependencias de Maven en pom.xml:

      org.apache.httpcomponents httpclient 4.0.1 compile   org.apache.httpcomponents httpmime 4.0.1 compile  

    Si el tamaño de los archivos JAR es importante (por ejemplo, en el caso de un applet), también se puede usar httpmime directamente con java.net.HttpURLConnection en lugar de HttpClient.

     httpclient-4.2.4: 423KB httpmime-4.2.4: 26KB httpcore-4.2.4: 222KB commons-codec-1.6: 228KB commons-logging-1.1.1: 60KB Sum: 959KB httpmime-4.2.4: 26KB httpcore-4.2.4: 222KB Sum: 248KB 

    Código:

     HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setRequestMethod("POST"); FileBody fileBody = new FileBody(new File(fileName)); MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.STRICT); multipartEntity.addPart("file", fileBody); connection.setRequestProperty("Content-Type", multipartEntity.getContentType().getValue()); OutputStream out = connection.getOutputStream(); try { multipartEntity.writeTo(out); } finally { out.close(); } int status = connection.getResponseCode(); ... 

    Dependencia en pom.xml:

      org.apache.httpcomponents httpmime 4.2.4  

    Use este código para cargar imágenes o cualquier otro archivo al servidor usando la publicación en varias partes.

     import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.BasicResponseHandler; import org.apache.http.impl.client.DefaultHttpClient; public class SimplePostRequestTest { public static void main(String[] args) throws UnsupportedEncodingException, IOException { HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("http://sofes.miximages.com/http/cd.png")); StringBody id = new StringBody("3"); MultipartEntity reqEntity = new MultipartEntity(); reqEntity.addPart("upload_image", bin); reqEntity.addPart("id", id); reqEntity.addPart("image_title", new StringBody("CoolPic")); httppost.setEntity(reqEntity); System.out.println("Requesting : " + httppost.getRequestLine()); ResponseHandler responseHandler = new BasicResponseHandler(); String responseBody = httpclient.execute(httppost, responseHandler); System.out.println("responseBody : " + responseBody); } catch (ClientProtocolException e) { } finally { httpclient.getConnectionManager().shutdown(); } } } 

    requiere que se suban los archivos inferiores.

    las bibliotecas son httpclient-4.1.2.jar, httpcore-4.1.2.jar, httpmime-4.1.2.jar, httpclient-cache-4.1.2.jar, commons-codec.jar y commons-logging-1.1.1.jar para estar en classpath.

    También puede usar REST Assured, que se basa en HTTP Client. Es muy sencillo:

     given().multiPart(new File("/somedir/file.bin")).when().post("/fileUpload"); 

    httpcomponents-client-4.0.1 funcionó para mí. Sin embargo, tuve que agregar el apache-mime4j-0.6.jar externo apache-mime4j-0.6.jar ( org.apache.james.mime4j ), de lo contrario, reqEntity.addPart("bin", bin); no comstackría Ahora está funcionando como el encanto.

    Encontré esta muestra en la Guía de inicio rápido de Apache. Es para la versión 4.5:

     /** * Example how to use multipart/form encoded POST request. */ public class ClientMultipartFormPost { public static void main(String[] args) throws Exception { if (args.length != 1) { System.out.println("File path not given"); System.exit(1); } CloseableHttpClient httpclient = HttpClients.createDefault(); try { HttpPost httppost = new HttpPost("http://localhost:8080" + "/servlets-examples/servlet/RequestInfoExample"); FileBody bin = new FileBody(new File(args[0])); StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN); HttpEntity reqEntity = MultipartEntityBuilder.create() .addPart("bin", bin) .addPart("comment", comment) .build(); httppost.setEntity(reqEntity); System.out.println("executing request " + httppost.getRequestLine()); CloseableHttpResponse response = httpclient.execute(httppost); try { System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); HttpEntity resEntity = response.getEntity(); if (resEntity != null) { System.out.println("Response content length: " + resEntity.getContentLength()); } EntityUtils.consume(resEntity); } finally { response.close(); } } finally { httpclient.close(); } } } 

    Tenemos una implementación java pura de envío de formularios multiparte sin usar dependencias externas o bibliotecas fuera de jdk. Consulte https://github.com/atulsm/https-multipart-purejava/blob/master/src/main/java/com/atul/MultipartPure.java

     private static String body = "{\"key1\":\"val1\", \"key2\":\"val2\"}"; private static String subdata1 = "@@ -2,3 +2,4 @@\r\n"; private static String subdata2 = "subdata2"; public static void main(String[] args) throws Exception{ String url = "https://" + ip + ":" + port + "/dataupload"; String token = "Basic "+ Base64.getEncoder().encodeToString((userName+":"+password).getBytes()); MultipartBuilder multipart = new MultipartBuilder(url,token); multipart.addFormField("entity", "main", "application/json",body); multipart.addFormField("attachment", "subdata1", "application/octet-stream",subdata1); multipart.addFormField("attachment", "subdata2", "application/octet-stream",subdata2); List response = multipart.finish(); for (String line : response) { System.out.println(line); } }