2009-09-04 11 views
78

Nei giorni della versione 3.x di Apache Commons HttpClient, fare una richiesta multipart/form-data post è stato possibile (an example from 2004). Purtroppo questo non è più possibile in version 4.0 of HttpClient.Come posso creare una richiesta POST multipart/form-data utilizzando Java?

Per la nostra attività principale "HTTP", multipart è in qualche modo fuori ambito. Ci piacerebbe utilizzare il codice multipart mantenuto da qualche altro progetto per il quale è in ambito, ma non ne sono a conoscenza. Abbiamo provato a spostare il codice multipart a commons-codec alcuni anni , ma non sono partito. Oleg ha recentemente citato un altro progetto con codice di analisi multiparte e potrebbe essere interessato allo nel nostro codice di formattazione multipart. Non conosco lo stato attuale su quello. (http://www.nabble.com/multipart-form-data-in-4.0-td14224819.html)

È qualcuno a conoscenza di qualsiasi libreria Java che mi permette di scrivere un client HTTP che può fare una richiesta POST multipart/form-data?

Sfondo: voglio utilizzare lo Remote API of Zoho Writer.

+0

Vedere anche - http://bayou.io/release/1.0/docs/http/Http_Client.html – ZhongYu

risposta

133

Utilizziamo HttpClient 4.x per creare post di file multipart.

UPDATE: A partire dal HttpClient 4.3, alcune classi sono state deprecate. Ecco il codice con le nuove 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(); 

Di seguito è il frammento di originale di codice con deprecato 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, la roba più parti è stato spostato al org.apache.httpcomponents-httpmime-4.0 ! Potrebbe essere citato da qualche parte:/ –

+0

Ho provato il codice aggiornato che funziona bene con file di piccole dimensioni ma non funziona con file di grandi dimensioni. Potete aiutarmi con questa [domanda] (http://stackoverflow.com/questions/25850077/how-to-upload-large-files-by-multipart-request-in-java) – abi1964

+0

Ciao ZZ, ho fatto la modifica di cui sopra nel mio codice, tuttavia, ora sto affrontando un nuovo problema: il mio endpoint REST non accetta la richiesta. Si aspetta i seguenti parametri: ~ @ ID stringa finale PathVariable, @RequestParam ("immagine") immagine finale MultipartFile, @RequestParam ("l") stringa finale l, @RequestParam ("lo") stringa finale lo, @RequestParam ("bac") bac stringa finale, @RequestParam ("cac") stringa finale cac, @RequestParam ("m") stringa finale m ... In precedenza, la richiesta veniva accettata. Ma ora sto ricevendo 500 errori. Qualche idea sul perché questo potrebbe accadere? – Logan

2

httpcomponents-client-4.0.1 ha lavorato per me. Tuttavia, ho dovuto aggiungere il vaso esterno apache-mime4j-0.6.jar (org.apache.james.mime4j) altrimenti reqEntity.addPart("bin", bin); non sarebbe la compilazione. Ora funziona come un fascino.

34

Queste sono le dipendenze Maven che ho.

del codice 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 Dipendenze in 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 per l'aggiunta di dipendenze Maven. Che fa risparmiare tempo! –

+1

avrete bisogno anche di httpcore, almeno nella 4.2, per la classe 'HttpEntity' – alalonde

4

È inoltre possibile utilizzare REST Assured che si basa sul client HTTP. E 'molto semplice:

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

Assumerà un nome di controllo chiamato" file ". Se hai un nome di controllo diverso, devi specificarlo: 'multiPart (" controlName ", new File ("/somedir/file.bin "))', vedi https://github.com/rest-assured/rest -assured/wiki/Usage # multi-part-form-data – asmaier

14

Se la dimensione degli elementi JAR (ad esempio in caso di applet), si può anche utilizzare direttamente httpmime con java.net.HttpURLConnection anziché 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 

Codice:

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

dipendenza nel pom.xml:

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

FileBody da dove proviene? C'è un modo (facile) per non utilizzare apace.httpcomponents? –

4

Utilizzare questo codice per caricare immagini o altri file sul server utilizzando post in multipart.

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

} 

richiede i seguenti file da caricare.

librerie sono httpclient-4.1.2.jar, httpcore-4.1.2.jar, httpmime-4.1.2.jar, httpclient-cache-4.1.2.jar, commons-codec.jar e commons-logging-1.1.1.jar di essere nel classpath.

0

Abbiamo una pura implementazione java di invio multiparte senza utilizzare dipendenze esterne o librerie esterne a jdk. Fare riferimento 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); 
    } 
} 
Problemi correlati