web-dev-qa-db-fra.com

Client Java HTTP pour télécharger le fichier sur POST

Je développe un client J2ME qui doit télécharger un fichier sur un Servlet à l'aide de HTTP.

La partie servlet est couverte avec Apache Commons FileUpload

protected void doPost(HttpServletRequest request, HttpServletResponse response) 
{       

    ServletFileUpload upload = new ServletFileUpload();
    upload.setSizeMax(1000000);

    File fileItems = upload.parseRequest(request);

    // Process the uploaded items
    Iterator iter = fileItems.iterator();
    while (iter.hasNext()) {
        FileItem item = (FileItem) iter.next();
        File file = new File("\files\\"+item.getName());
        item.write(file);
    }
}

Commons Upload semble ne pouvoir télécharger que des fichiers en plusieurs parties, mais pas d'application/octect-stream.

Mais pour le côté client, il n’existe aucune classe Multipart, et dans ce cas, il n’est pas possible d’utiliser une bibliothèque HttpClient.

Une autre option pourrait être d'utiliser le téléchargement HTTP Chunk, mais je n'ai pas trouvé d'exemple clair de la façon dont cela pourrait être implémenté, en particulier du côté servlet.

Mes choix sont les suivants: - Implémenter un servlet pour le téléchargement de bloc http - Implémenter un client brut pour la création multipart http

Je ne sais pas comment implémenter aucune des options ci-dessus .. Une suggestion?

12
Clark Ku

L'envoi de fichiers via HTTP est supposé se faire avec le codage multipart/form-data. Votre servlet est bon car il utilise déjà Apache Commons FileUpload pour analyser une requête multipart/form-data.

Votre partie client, toutefois, ne semble pas très bien car vous écrivez apparemment le contenu du fichier brut dans le corps de la demande. Vous devez vous assurer que votre client envoie une demande multipart/form-data appropriée. Cela dépend de l'API utilisée pour envoyer la requête HTTP. Si c'est simplement Vanilla Java.net.URLConnection, vous pouvez trouver un exemple concret quelque part au bas de cette réponse . Si vous utilisez Apache HttpComponents Client pour cela, voici un exemple concret:

HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);

MultipartEntity entity = new MultipartEntity();
entity.addPart("file", new FileBody(file));
post.setEntity(entity);

HttpResponse response = client.execute(post);
// ...

Unrelated au problème concret, il y a un bogue dans le code côté serveur:

File file = new File("\files\\"+item.getName());
item.write(file);

Cela écrasera potentiellement tout fichier précédemment chargé portant le même nom. Je suggérerais d'utiliser File#createTempFile() pour cela à la place.

String name = FilenameUtils.getBaseName(item.getName());
String ext = FilenameUtils.getExtension(item.getName());
File file = File.createTempFile(name + "_", "." + ext, new File("/files"));
item.write(file);
28
BalusC

Le code suivant peut être utilisé pour télécharger un fichier avec HTTP Client 4.x (La réponse ci-dessus utilise MultipartEntity, désormais obsolète)

import org.Apache.http.HttpResponse;
import org.Apache.http.client.methods.HttpPost;
import org.Apache.http.entity.mime.MultipartEntityBuilder;
import org.Apache.http.entity.mime.content.FileBody;
import org.Apache.http.impl.client.CloseableHttpClient;
import org.Apache.http.impl.client.HttpClients;
import org.Apache.http.util.EntityUtils;

String uploadFile(String url, File file) throws IOException
{
    HttpPost post = new HttpPost(url);
    post.setHeader("Accept", "application/json");
    _addAuthHeader(post);
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    // fileParamName should be replaced with parameter name your REST API expect.
    builder.addPart("fileParamName", new FileBody(file));
    //builder.addPart("optionalParam", new StringBody("true", ContentType.create("text/plain", Consts.ASCII)));
    post.setEntity(builder.build());
    HttpResponse response = getClient().execute(post);;
    int httpStatus = response.getStatusLine().getStatusCode();
    String responseMsg = EntityUtils.toString(response.getEntity(), "UTF-8");

    // If the returned HTTP response code is not in 200 series then
    // throw the error
    if (httpStatus < 200 || httpStatus > 300) {
        throw new IOException("HTTP " + httpStatus + " - Error during upload of file: " + responseMsg);
    }

    return responseMsg;
}

Vous aurez besoin des versions récentes des bibliothèques Apache suivantes: httpclient, httpcore, httpmime.

getClient() peut être remplacé par HttpClients.createDefault().

5
Hemant

Merci pour tout le code Ive sniped ... Voici quelques retour.

Gradle

compile "org.Apache.httpcomponents:httpclient:4.4"  
compile "org.Apache.httpcomponents:httpmime:4.4"



import Java.io.File;
import Java.io.IOException;
import Java.io.InputStream;
import Java.io.StringWriter;
import Java.util.Map;

import org.Apache.commons.io.IOUtils;
import org.Apache.http.HttpEntity;
import org.Apache.http.client.ClientProtocolException;
import org.Apache.http.client.methods.CloseableHttpResponse;
import org.Apache.http.client.methods.HttpGet;
import org.Apache.http.client.methods.HttpPost;
import org.Apache.http.entity.ContentType;
import org.Apache.http.entity.mime.MultipartEntityBuilder;
import org.Apache.http.entity.mime.content.FileBody;
import org.Apache.http.entity.mime.content.StringBody;
import org.Apache.http.impl.client.CloseableHttpClient;
import org.Apache.http.impl.client.HttpClients;


public class HttpClientUtils {

    public static String post(String postUrl, Map<String, String> params,
            Map<String, String> files) throws ClientProtocolException,
            IOException {
        CloseableHttpResponse response = null;
        InputStream is = null;
        String results = null;
        CloseableHttpClient httpclient = HttpClients.createDefault();

        try {

            HttpPost httppost = new HttpPost(postUrl);

            MultipartEntityBuilder builder = MultipartEntityBuilder.create();

            if (params != null) {
                for (String key : params.keySet()) {
                    StringBody value = new StringBody(params.get(key),
                            ContentType.TEXT_PLAIN);
                    builder.addPart(key, value);
                }
            }

            if (files != null && files.size() > 0) {
                for (String key : files.keySet()) {
                    String value = files.get(key);
                    FileBody body = new FileBody(new File(value));
                    builder.addPart(key, body);
                }
            }

            HttpEntity reqEntity = builder.build();
            httppost.setEntity(reqEntity);

            response = httpclient.execute(httppost);
            // assertEquals(200, response.getStatusLine().getStatusCode());

            HttpEntity entity = response.getEntity();
            if (entity != null) {
                is = entity.getContent();
                StringWriter writer = new StringWriter();
                IOUtils.copy(is, writer, "UTF-8");
                results = writer.toString();
            }

        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (Throwable t) {
                // No-op
            }

            try {
                if (response != null) {
                    response.close();
                }
            } catch (Throwable t) {
                // No-op
            }

            httpclient.close();
        }

        return results;
    }

    public static String get(String getStr) throws IOException,
            ClientProtocolException {
        CloseableHttpResponse response = null;
        InputStream is = null;
        String results = null;
        CloseableHttpClient httpclient = HttpClients.createDefault();

        try {
            HttpGet httpGet = new HttpGet(getStr);
            response = httpclient.execute(httpGet);

            assertEquals(200, response.getStatusLine().getStatusCode());

            HttpEntity entity = response.getEntity();
            if (entity != null) {
                is = entity.getContent();
                StringWriter writer = new StringWriter();
                IOUtils.copy(is, writer, "UTF-8");
                results = writer.toString();
            }

        } finally {

            try {
                if (is != null) {
                    is.close();
                }
            } catch (Throwable t) {
                // No-op
            }

            try {
                if (response != null) {
                    response.close();
                }
            } catch (Throwable t) {
                // No-op
            }

            httpclient.close();
        }

        return results;
    }

}
0
Peter