2009-09-04 17 views
78

En la época de la versión 3.x de Apache Commons HttpClient, era posible realizar una solicitud POST multipart/form-data (an example from 2004). Lamentablemente, esto ya no es posible en version 4.0 of HttpClient.¿Cómo puedo hacer una solicitud POST multipart/form-data utilizando Java?

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

¿Hay alguien al tanto de cualquier biblioteca de Java que me permite escribir un cliente HTTP que puede hacer una solicitud POST multipart/form-data?

Antecedentes: deseo usar el Remote API of Zoho Writer.

+0

ver también - http://bayou.io/release/1.0/docs/http/Http_Client.html – ZhongYu

Respuesta

133

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 en desuso. Aquí está el código con el nuevo 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 original de código con obsoleta HttpClient 4.0 API:

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(); 
+60

Ah, el material de varias partes se ha trasladado a org.apache.httpcomponents-httpmime-4.0 ! Podría ser mencionado en alguna parte:/ –

+0

He intentado con tu código actualizado que funciona bien con archivos pequeños pero no funciona con archivos de gran tamaño. ¿Puede ayudarme con esta [pregunta] (http://stackoverflow.com/questions/25850077/how-to-upload-large-files-by-multipart-request-in-java) – abi1964

+0

Hola ZZ, he hecho el cambio anterior en mi código, sin embargo, ahora estoy enfrentando un nuevo problema: mi punto final REST no está aceptando la solicitud. Se esperan los siguientes parámetros: ~ @ PathVariable final String id, @RequestParam ("image") imagen final de MultipartFile, @RequestParam ("l") final String l, @RequestParam ("lo") final String lo, @RequestParam ("bac") final String bac, @RequestParam ("cac") final String cac, @RequestParam ("m") final String m ... Anteriormente, la solicitud se estaba aceptando. Pero ahora estoy obteniendo 500 de error. Alguna idea de por qué esto esta pasando? – Logan

2

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

34

Estas son las dependencias de Maven que tengo.

Código 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); 

Maven Dependencias en pom.xml:

<dependency> 
    <groupId>org.apache.httpcomponents</groupId> 
    <artifactId>httpclient</artifactId> 
    <version>4.0.1</version> 
    <scope>compile</scope> 
</dependency> 
<dependency> 
    <groupId>org.apache.httpcomponents</groupId> 
    <artifactId>httpmime</artifactId> 
    <version>4.0.1</version> 
    <scope>compile</scope> 
</dependency> 
+4

+1 para agregar dependencias Maven. ¡Ahorrar tiempo! –

+1

también necesitará httpcore, al menos en 4.2, para la clase 'HttpEntity' – alalonde

4

También puede utilizar REST Assured que se basa en cliente HTTP. Es muy simple:

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

Asumirá un nombre de control llamado" archivo ". Si tiene un nombre de control diferente, entonces debe especificarlo: 'multiPart (" controlName ", nuevo archivo ("/somedir/file.bin "))', consulte https://github.com/rest-assured/rest. -assured/wiki/Usage # multi-part-form-data – asmaier

14

Si el tamaño de los asuntos JAR (por ejemplo, en caso de aplicación), también se puede utilizar directamente httpmime 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:

<dependency> 
    <groupId>org.apache.httpcomponents</groupId> 
    <artifactId>httpmime</artifactId> 
    <version>4.2.4</version> 
</dependency> 
+0

FileBody de dónde vino esto? ¿Hay alguna manera (fácil) de no usar los componentes de apace.http? –

4

Utilice este código para cargar imágenes o cualquier otro archivo en el servidor mediante 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://192.168.0.102/uploadtest/upload_photo"); 

     try { 
      FileBody bin = new FileBody(new File("/home/ubuntu/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<String> responseHandler = new BasicResponseHandler(); 
      String responseBody = httpclient.execute(httppost, responseHandler); 
      System.out.println("responseBody : " + responseBody); 

     } catch (ClientProtocolException e) { 

     } finally { 
      httpclient.getConnectionManager().shutdown(); 
     } 
    } 

} 

requiere de los siguientes archivos para cargar.

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 estar en la ruta de clase.

0

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 = "<data>subdata2</data>"; 

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<String> response = multipart.finish();   
    for (String line : response) { 
     System.out.println(line); 
    } 
} 
Cuestiones relacionadas