Envoi d'images à l'aide de Http Post

129

Je souhaite envoyer une image du client Android au serveur Django en utilisant Http Post. L'image est choisie dans la galerie. À l'heure actuelle, j'utilise des paires de noms de valeur de liste pour envoyer les données nécessaires au serveur et recevoir des réponses de Django en JSON. La même approche peut-elle être utilisée pour les images (avec des URL pour les images intégrées dans les réponses JSON)?

De plus, quelle est la meilleure méthode: accéder aux images à distance sans les télécharger à partir du serveur ou les télécharger et les stocker dans un tableau Bitmap et les utiliser localement? Les images sont peu nombreuses (<10) et de petite taille (50 * 50 dip).

Tout tutoriel pour aborder ces problèmes serait très apprécié.

Modifier: les images choisies dans la galerie sont envoyées au serveur après mise à l'échelle à la taille requise.

Primal Pappachan
la source

Réponses:

144

Je vais supposer que vous connaissez le chemin et le nom de fichier de l'image que vous souhaitez télécharger. Ajoutez cette chaîne à votre NameValuePairutilisation imagecomme nom de clé.

L'envoi d'images peut être effectué à l'aide des bibliothèques HttpComponents . Téléchargez le dernier binaire HttpClient (actuellement 4.0.1 ) avec le package de dépendances et copiez apache-mime4j-0.6.jar-le httpmime-4.0.1.jardans votre projet et ajoutez-les à votre chemin de construction Java.

Vous devrez ajouter les importations suivantes à votre classe.

import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;

Vous pouvez maintenant créer un MultipartEntitypour joindre une image à votre demande POST. Le code suivant montre un exemple de procédure:

public void post(String url, List<NameValuePair> nameValuePairs) {
    HttpClient httpClient = new DefaultHttpClient();
    HttpContext localContext = new BasicHttpContext();
    HttpPost httpPost = new HttpPost(url);

    try {
        MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);

        for(int index=0; index < nameValuePairs.size(); index++) {
            if(nameValuePairs.get(index).getName().equalsIgnoreCase("image")) {
                // If the key equals to "image", we use FileBody to transfer the data
                entity.addPart(nameValuePairs.get(index).getName(), new FileBody(new File (nameValuePairs.get(index).getValue())));
            } else {
                // Normal string data
                entity.addPart(nameValuePairs.get(index).getName(), new StringBody(nameValuePairs.get(index).getValue()));
            }
        }

        httpPost.setEntity(entity);

        HttpResponse response = httpClient.execute(httpPost, localContext);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

J'espère que cela vous aide un peu dans la bonne direction.

Piro
la source
6
Je recommanderais certainement ceci. De cette façon, vous pouvez probablement utiliser les fonctionnalités de Django pour recevoir l'image et la stocker facilement. Une autre façon serait d'encoder le flux d'octets de l'image dans une chaîne encodée en base64 et de la décoder côté serveur. Mais ce serait trop compliqué à mon avis et pas la voie à suivre.
Piro
6
Hé les gars, y a-t-il un moyen de faire ça sans MultipartEntity? Je ne veux VRAIMENT pas importer tout Apache HC uniquement pour ces 4 classes. :-(
Neil Traft
6
Ajoutez simplement un 2ème paramètre à FileBodyvotre type Mime souhaité. Ex:new FileBody(new File (nameValuePairs.get(index).getValue()), "image/jpeg")
Piro
4
On dirait que le multipartite est obsolète?
Nanne
1
@Piro Je pensais aussi éditer votre réponse. L'entité en plusieurs parties est dépréciée avec la version du corps de chaîne que vous utilisez. La raison pour laquelle je ne modifie pas est que je ne pourrais pas lier toutes les données dans namevaluepairs comme vous l'avez fait.
Argument illégal le
15

Version 4.3.5 Code mis à jour

  • httpclient-4.3.5.jar
  • httpcore-4.3.2.jar
  • httpmime-4.3.5.jar

Depuis MultipartEntityest obsolète . Veuillez consulter le code ci-dessous.

String responseBody = "failure";
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);

String url = WWPApi.URL_USERS;
Map<String, String> map = new HashMap<String, String>();
map.put("user_id", String.valueOf(userId));
map.put("action", "update");
url = addQueryParams(map, url);

HttpPost post = new HttpPost(url);
post.addHeader("Accept", "application/json");

MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(MIME.UTF8_CHARSET);

if (career != null)
    builder.addTextBody("career", career, ContentType.create("text/plain", MIME.UTF8_CHARSET));
if (gender != null)
    builder.addTextBody("gender", gender, ContentType.create("text/plain", MIME.UTF8_CHARSET));
if (username != null)
    builder.addTextBody("username", username, ContentType.create("text/plain", MIME.UTF8_CHARSET));
if (email != null)
    builder.addTextBody("email", email, ContentType.create("text/plain", MIME.UTF8_CHARSET));
if (password != null)
    builder.addTextBody("password", password, ContentType.create("text/plain", MIME.UTF8_CHARSET));
if (country != null)
    builder.addTextBody("country", country, ContentType.create("text/plain", MIME.UTF8_CHARSET));
if (file != null)
    builder.addBinaryBody("Filedata", file, ContentType.MULTIPART_FORM_DATA, file.getName());

post.setEntity(builder.build());

try {
    responseBody = EntityUtils.toString(client.execute(post).getEntity(), "UTF-8");
//  System.out.println("Response from Server ==> " + responseBody);

    JSONObject object = new JSONObject(responseBody);
    Boolean success = object.optBoolean("success");
    String message = object.optString("error");

    if (!success) {
        responseBody = message;
    } else {
        responseBody = "success";
    }

} catch (Exception e) {
    e.printStackTrace();
} finally {
    client.getConnectionManager().shutdown();
}
AZ_
la source
Quels packages JAR sont nécessaires?
3
httpclient-4.3.5.jar httpcore-4.3.2.jar httpmime-4.3.5.jar
AZ_
Que renvoie addQueryParams?
San
11

La bibliothèque loopj peut être utilisée directement à cette fin:

SyncHttpClient client = new SyncHttpClient();
RequestParams params = new RequestParams();
params.put("text", "some string");
params.put("image", new File(imagePath));

client.post("http://example.com", params, new TextHttpResponseHandler() {
  @Override
  public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
    // error handling
  }

  @Override
  public void onSuccess(int statusCode, Header[] headers, String responseString) {
    // success
  }
});

http://loopj.com/

vonox7
la source
5

J'ai beaucoup de mal à essayer d'implémenter la publication d'une image du client Android sur le servlet en utilisant httpclient-4.3.5.jar, httpcore-4.3.2.jar, httpmime-4.3.5.jar. J'ai toujours une erreur d'exécution. J'ai découvert qu'en gros, vous ne pouvez pas utiliser ces jars avec Android car Google utilise une ancienne version de HttpClient sous Android. L'explication est ici http://hc.apache.org/httpcomponents-client-4.3.x/android-port.html . Vous devez obtenir le jar httpclientandroidlib-1.2.1 à partir de la bibliothèque Android http-client . Modifiez ensuite vos importations de or.apache.http.client en ch.boye.httpclientandroidlib. J'espère que cela t'aides.

DavidC
la source
-13

Je fais généralement cela dans le thread qui gère la réponse json:

try {
  Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(imageUrl).getContent());
} catch (MalformedURLException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}

Si vous devez effectuer des transformations sur l'image, vous voudrez créer un dessinable au lieu d'un bitmap.

Dylan McClung
la source
3
La question est de savoir comment publier une image et non comment l’obtenir.
dwbrito