Envío de imágenes usando Http Post

129

Quiero enviar una imagen del cliente de Android al servidor de Django usando Http Post. La imagen se elige de la galería. En este momento, estoy usando pares de nombres de valores de lista para enviar los datos necesarios al servidor y recibir respuestas de Django en JSON. ¿Se puede usar el mismo enfoque para imágenes (con URL para imágenes incrustadas en respuestas JSON)?

Además, ¿cuál es un mejor método: acceder a las imágenes de forma remota sin descargarlas del servidor o descargarlas y almacenarlas en una matriz de mapas de bits y usarlas localmente? Las imágenes son pocas en número (<10) y de tamaño pequeño (50 * 50 dip).

Cualquier tutorial para abordar estos problemas sería muy apreciado.

Editar: las imágenes elegidas de la galería se envían al servidor después de escalarlo al tamaño requerido.

Pappachan primigenio
fuente

Respuestas:

144

Asumiré que conoce la ruta y el nombre de archivo de la imagen que desea cargar. Agregue esta cadena a su NameValuePairuso imagecomo el nombre clave.

El envío de imágenes se puede hacer usando las bibliotecas HttpComponents . Descargue el último binario HttpClient (actualmente 4.0.1 ) con paquete de dependencias y copie apache-mime4j-0.6.jary httpmime-4.0.1.jara su proyecto y agréguelos a su ruta de compilación Java.

Deberá agregar las siguientes importaciones a su clase.

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;

Ahora puede crear una MultipartEntitypara adjuntar una imagen a su solicitud POST. El siguiente código muestra un ejemplo de cómo hacer esto:

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

Espero que esto te ayude un poco en la dirección correcta.

Piro
fuente
66
Definitivamente lo recomendaría. De esta manera, probablemente pueda usar las funciones de Django para recibir la imagen y almacenarla fácilmente. Otra forma sería codificar la secuencia de bytes desde la imagen a una cadena codificada en base64 y decodificarla del lado del servidor. Pero esto sería una molestia demasiado en mi opinión y no el camino a seguir.
Piro
66
Hola chicos, ¿hay alguna manera de hacer esto sin MultipartEntity? REALMENTE no quiero importar todo Apache HC solo para esas 4 clases. :-(
Neil Traft
66
Simplemente agregue un segundo parámetro a FileBody su Tipo Mime deseado. Por ejemplo:new FileBody(new File (nameValuePairs.get(index).getValue()), "image/jpeg")
Piro
44
Parece que la multipartentidad está en desuso?
Nanne
1
@Piro Yo también estaba pensando en editar tu respuesta. La entidad multiparte se deprecia junto con la versión del cuerpo de la cadena que está utilizando. La razón por la que no estoy editando es porque no pude vincular todos los datos en namevaluepairs como lo ha hecho.
Argumento ilegal
15

Código actualizado de la versión 4.3.5

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

Desde MultipartEntityha quedado en desuso . Por favor vea el código a continuación.

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();
}
ARIZONA_
fuente
¿Qué paquetes jar se necesitan?
3
httpclient-4.3.5.jar httpcore-4.3.2.jar httpmime-4.3.5.jar
AZ_
¿Qué devuelve addQueryParams?
San
11

La biblioteca loopj se puede usar directamente para este propósito:

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
fuente
5

Me costó mucho tratar de implementar la publicación de una imagen del cliente de Android en el servlet usando httpclient-4.3.5.jar, httpcore-4.3.2.jar, httpmime-4.3.5.jar. Siempre recibí un error de tiempo de ejecución. Descubrí que básicamente no puedes usar estos frascos con Android ya que Google está usando una versión anterior de HttpClient en Android. La explicación está aquí http://hc.apache.org/httpcomponents-client-4.3.x/android-port.html . Debe obtener el jar httpclientandroidlib-1.2.1 de la biblioteca android http-client . Luego cambie sus importaciones de or.apache.http.client a ch.boye.httpclientandroidlib. Espero que esto ayude.

DavidC
fuente
-13

Usualmente hago esto en el hilo que maneja la respuesta json:

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

Si necesita hacer transformaciones en la imagen, querrá crear un Drawable en lugar de un Bitmap.

Dylan McClung
fuente
3
La pregunta es cómo publicar una imagen y no cómo obtenerla.
dwbrito