2009-09-04 8 views
78

In den Tagen der Version 3.x von Apache Commons HttpClient, eine multipart/form-Daten POST-Anfrage war möglich (an example from 2004). Leider ist dies in version 4.0 of HttpClient nicht mehr möglich.Wie kann ich eine mehrteilige/Formulardaten-POST-Anfrage mit Java machen?

Für unsere Kernaktivität "HTTP" ist mehrteilig etwas außerhalb des Geltungsbereichs. Wir würden gerne Multipart-Code verwenden, der von einem anderen Projekt verwaltet wird, für das es in Reichweite ist, aber mir ist nichts bekannt. Wir haben versucht, den Multipart-Code in Commons-Codec vor ein paar Jahren zu verschieben, aber ich habe dort nicht abgehoben. Oleg erwähnte kürzlich ein weiteres Projekt, das einen mehrteiligen Parsing-Code hat und in unserem mehrteiligen Formatierungscode interessiert sein könnte. Ich kenne den aktuellen Status nicht. (http://www.nabble.com/multipart-form-data-in-4.0-td14224819.html)

Ist jemand Kenntnis von einer Java-Bibliothek, die mir ein HTTP-Client schreiben kann, die eine multipart/form-data POST-Anfrage machen können?

Hintergrund: Ich möchte die Remote API of Zoho Writer verwenden.

+0

siehe auch - http://bayou.io/release/1.0/docs/http/Http_Client.html – ZhongYu

Antwort

133

Wir verwenden HttpClient 4.x, um mehrteilige Datei Post zu machen.

UPDATE: Ab Httpclient 4.3 haben einige Klassen veraltet. Hier ist der Code mit neuen 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(); 

Im Folgenden wird der ursprüngliche Code-Snippet mit veraltet 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 hat sich die mehrteilige Sachen verschoben org.apache.httpcomponents-httpmime-4.0 ! Könnte irgendwo erwähnt werden:/ –

+0

Ich habe versucht, Ihren aktualisierten Code, der mit kleinen Dateien funktioniert aber nicht mit großen Dateien funktioniert. Kannst du mir dabei helfen [Frage] (http://stackoverflow.com/questions/25850077/how-to-upload-large-files-by-multipart-request-in-java) – abi1964

+0

Hallo ZZ, habe ich gemacht Die obige Änderung in meinem Code, aber ich bin jetzt ein neues Problem konfrontiert - mein REST-Endpunkt akzeptiert die Anfrage nicht. Es erwartet die folgenden Parameter: ~ @ PathVariable final Zeichenfolgen-ID, @RequestParam ("Bild") final MultipartFile-Bild, @RequestParam ("l") final Zeichenfolge l, @RequestParam ("lo") final Zeichenfolge lo, @RequestParam ("bac") final Zeichenfolge bac, @RequestParam ("cac") final Zeichenfolge cac, @RequestParam ("m") final Zeichenfolge m ... Zuvor wurde die Anforderung akzeptiert. Aber jetzt bekomme ich 500 Fehler. Irgendwelche Ideen, warum das passieren könnte? – Logan

2

httpcomponents-client-4.0.1 für mich gearbeitet. Allerdings musste ich das externe Glas apache-mime4j-0.6.jar (org.apache.james.mime4j) hinzufügen, sonst reqEntity.addPart("bin", bin); würde nicht kompilieren. Jetzt funktioniert es wie Charme.

34

Dies sind die Maven Abhängigkeiten, die ich habe.

Java-Code:

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 Abhängigkeiten 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 zum Hinzufügen von Maven-Abhängigkeiten. Zeitersparnis! –

+1

benötigen Sie auch httpcore, mindestens in 4.2, für die 'HttpEntity' Klasse – alalonde

4

Sie können auch REST Assured verwenden, die auf HTTP-Client aufbaut. Es ist sehr einfach:

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

Es wird eine Kontrolle namens" Datei "annehmen. Wenn Sie einen anderen Kontrollnamen haben, müssen Sie ihn angeben: 'multiPart (" controlName ", neue Datei ("/somedir/file.bin "))', siehe https://github.com/rest-sured/rest -assured/wiki/Usage # multi-part-form-data – asmaier

14

Wenn Größe der JAR-Dateien Angelegenheiten (zum Beispiel im Fall von Applet), kann man auch direkt httpmime verwendet mit java.net.HttpURLConnection statt 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 

Code:

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

Abhängigkeit in pom.xml:

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

FileBody woher kommt das? Gibt es eine (einfache) Möglichkeit, apace.httpcomponents nicht zu verwenden? –

4

Verwenden Sie diesen Code zum Hochladen von Bildern oder anderen Dateien auf den Server mithilfe von 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(); 
     } 
    } 

} 

es erfordert unter Dateien zum Hochladen.

Bibliotheken sind httpclient-4.1.2.jar, httpcore-4.1.2.jar, httpmime-4.1.2.jar, httpclient-cache-4.1.2.jar, commons-codec.jar und commons-logging-1.1.1.jar in Classpath zu sein.

0

Wir haben eine reine Java-Implementierung von multipart-Formular übergeben, ohne externe Abhängigkeiten oder Bibliotheken außerhalb jdk zu verwenden. Siehe 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); 
    } 
}