2009-09-04 8 views
78

W dniach wersji 3.x Apache Commons HttpClient, możliwe było wysłanie żądania POST dla wielu arkuszy/danych formularzy (an example from 2004). Niestety nie jest to już możliwe w version 4.0 of HttpClient.Jak mogę utworzyć żądanie POST wielostronicowe/dane formularza za pomocą Java?

Dla naszej podstawowej działalności "HTTP", wieloczęściowy jest nieco poza zakresem. . Chcielibyśmy użyć kodu wieloczęściowego obsługiwanego przez jakiś inny projekt, dla którego jest on w zakresie, ale nie jestem tego świadomy. Próbowaliśmy przenieść kod wieloczęściowy do commons-kodek kilka lat temu temu, ale nie wystartowałem tam. Oleg wspominał ostatnio o innym projekcie , który ma wieloczęściowy kod parsowania i może być zainteresowany w naszym kodowaniu wieloczęściowym. Nie znam aktualnego stanu na tym . (http://www.nabble.com/multipart-form-data-in-4.0-td14224819.html)

Czy ktoś wie o jakiejkolwiek bibliotece Java, która pozwala mi pisać klienta HTTP, który może utworzyć żądanie POST wielostronicowe/dane formularza?

Tło: chcę użyć Remote API of Zoho Writer.

+0

patrz także - http://bayou.io/release/1.0/docs/http/Http_Client.html – ZhongYu

Odpowiedz

133

Używamy HttpClient 4.x do tworzenia wieloczęściowych postów plików.

UPDATE: Od httpclient 4,3, niektóre klasy są nieaktualne. Oto kod z nowego 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(); 

Poniżej jest oryginalny fragment kodu z przestarzałe 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

Ach, wieloczęściowy rzeczy został przeniesiony do org.apache.httpcomponents-httpmime-4.0 ! Można gdzieś wspomnieć:/ –

+0

Próbowałem twój zaktualizowany kod, który działa dobrze z małymi plikami, ale nie działa z dużymi plikami. Czy możesz mi pomóc w tym [pytanie] (http://stackoverflow.com/questions/25850077/how-to-upload-large-files-by-multipart-request-in-java) – abi1964

+0

Witam ZZ, zrobiłem powyższa zmiana w moim kodzie, jednak mam teraz do czynienia z nowym problemem - mój punkt końcowy REST nie przyjmuje żądania. Oczekuje następujących parametrów: ~ @ PathVariable final id ciąg, @RequestParam ("image") ostateczny obraz MultipartFile, @RequestParam ("l") końcowy String l, @RequestParam ("lo") końcowy String lo, @RequestParam ("bac") final String bac, @RequestParam ("cac") final String cac, @RequestParam ("m") final String m ... Poprzednio wniosek został zaakceptowany. Ale teraz dostaję 500 błędów. Jakieś pomysły, dlaczego tak się dzieje? – Logan

2

httpcomponents-client-4.0.1 pracował dla mnie. Jednak musiałem dodać zewnętrzny słoik apache-mime4j-0.6.jar (org.apache.james.mime4j) inaczej reqEntity.addPart("bin", bin); nie skompilowałbym. Teraz działa jak urok.

34

Są to zależności Maven, które posiadam.

kod 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 Zależności w 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 za dodanie zależności Mavena. Oszczędność czasu! –

+1

będziesz potrzebował również httpcore, przynajmniej w 4.2, dla klasy 'HttpEntity' – alalonde

4

Można również użyć REST Assured który bazuje na klienta HTTP. To bardzo proste:

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

Przyjmie nazwę kontrolną o nazwie" file ". Jeśli masz inną nazwę kontrolną, musisz ją określić: 'multiPart (" controlName ", nowy plik ("/somedir/file.bin "))', zobacz https://github.com/rest-assured/rest -assured/wiki/Usage # wieloczęściowa-forma-danych – asmaier

14

Jeśli wielkość sprawach słoikach (na przykład w przypadku apletu), można również korzystać bezpośrednio httpmime z java.net.HttpURLConnection zamiast 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 

Kod:

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

Zależność w pom.xml:

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

FileBody skąd to pochodzi? Czy istnieje (łatwy) sposób, aby nie używać apace.httpcomponents? –

4

Ten kod służy do przesyłania obrazów lub innych plików na serwer za pomocą posta w trybie wieloczęściowym.

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

} 

Wymaga to przesłania plików poniżej.

biblioteki są httpclient-4.1.2.jar, httpcore-4.1.2.jar, httpmime-4.1.2.jar, httpclient-cache-4.1.2.jar, commons-codec.jar i commons-logging-1.1.1.jar się w ścieżce klasy.

0

Mamy czystą implementację Java w postaci wieloczęściowego przesyłania bez użycia zewnętrznych zależności lub bibliotek poza jdk. Patrz 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); 
    } 
} 
Powiązane problemy