web-dev-qa-db-fra.com

Comment faire une demande multipart / form-data POST en utilisant Java?

À l'époque de la version 3.x d'Apache Commons HttpClient, il était possible d'effectuer une requête multipart/form-data POST ( exemple de 2004 ). Malheureusement, il s'agit n'est plus possible dans version 4.0 de HttpClient .

Pour notre activité principale "HTTP", le multipart est quelque peu en dehors de la portée. Nous aimerions utiliser du code en plusieurs parties géré par un autre projet pour lequel il est inclus, mais je n'en connais aucun. Nous avons essayé de transférer le code en plusieurs parties au codec commons il y a quelques années, mais je n'y suis pas allé. Oleg a récemment mentionné un autre projet qui comporte un code d’analyse en plusieurs parties et qui pourrait être intéressé par notre code de formatage en plusieurs parties. Je ne connais pas le statut actuel à ce sujet. ( http://www.nabble.com/multipart-form-data-in-4.0-td14224819.html )

Est-ce que quelqu'un est au courant de l'existence d'une bibliothèque Java qui me permet d'écrire un client HTTP pouvant effectuer une demande multipart/form-data POST?

Fond: Je veux utiliser le API distante de Zoho Writer .

86
lutz

Nous utilisons HttpClient 4.x pour créer des fichiers multipart post.

UPDATE : À partir de HttpClient 4.3 , certaines classes sont obsolètes. Voici le code avec la nouvelle 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();

Ci-dessous l'extrait de code d'origine avec API obsolète HttpClient 4.:

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();
144
ZZ Coder

Ce sont les dépendances Maven que j'ai.

Code 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);

Dépendances Maven dans 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>
39
Jaco van Niekerk

Si la taille des fichiers JAR est importante (par exemple, dans le cas d’une applet), vous pouvez également utiliser directement httpmime avec Java.net.HttpURLConnection au lieu 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

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

Dépendance dans pom.xml:

<dependency>
    <groupId>org.Apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
    <version>4.2.4</version>
</dependency>
18
anre

Utilisez ce code pour télécharger des images ou tout autre fichier sur le serveur à l’aide de 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();
        }
    }

}

il faut des fichiers ci-dessous pour télécharger.

les bibliothèques sont httpclient-4.1.2.jar,httpcore-4.1.2.jar,httpmime-4.1.2.jar,httpclient-cache-4.1.2.jar,commons-codec.jar et commons-logging-1.1.1.jar être dans classpath.

5
Java Man

Vous pouvez également utiliser REST Assured qui repose sur le client HTTP. C'est très simple:

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

httpcomponents-client-4.0.1 A fonctionné pour moi. Cependant, je devais ajouter le jar externe Apache-mime4j-0.6.jar (org.Apache.james.mime4j) sinon reqEntity.addPart("bin", bin); ne serait pas compilé. Maintenant, ça marche comme un charme.

2
Bob Yoplait

J'ai trouvé cet exemple dans Guide de démarrage rapide d'Apache. C'est pour la version 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();
        }
    }
}
1
Amber

Voici une solution qui ne nécessite aucune bibliothèque.

Cette routine transmet tous les fichiers du répertoire d:/data/mpf10 à "urlToConnect".

String boundary = Long.toHexString(System.currentTimeMillis());


URLConnection connection = new URL(urlToConnect).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
     writer = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));


     File dir = new File("d:/data/mpf10");

     for (File file : dir.listFiles()) {
           if (file.isDirectory()) {
                continue;
           }

           writer.println("--" + boundary);
           writer.println("Content-Disposition: form-data; name=\"" + file.getName() + "\"; filename=\"" + file.getName() + "\"");
           writer.println("Content-Type: text/plain; charset=UTF-8");
           writer.println();
           BufferedReader reader = null;
           try {
                reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
                for (String line; (line = reader.readLine()) != null;) {
                      writer.println(line);
                }
           } finally {
                if (reader != null) {
                      reader.close();
                }
           }
     }

     writer.println("--" + boundary + "--");
} finally {
     if (writer != null)
           writer.close();
}

// Connection is lazily executed whenever you request any status.
int responseCode = ((HttpURLConnection) connection).getResponseCode();
1
user1005939