Invio di immagini tramite Http Post


129

Voglio inviare un'immagine dal client Android al server Django usando Http Post. L'immagine è scelta dalla galleria. Al momento, sto usando il nome dell'elenco nome Pairs per inviare i dati necessari al server e ricevere risposte da Django in JSON. È possibile utilizzare lo stesso approccio per le immagini (con URL per le immagini incorporate nelle risposte JSON)?

Inoltre, qual è il metodo migliore: accedere alle immagini in remoto senza scaricarle dal server o scaricarle e archiviarle in un array Bitmap e utilizzarle localmente? Le immagini sono poche in numero (<10) e di piccole dimensioni (50 * 50 dip).

Qualsiasi tutorial per affrontare questi problemi sarebbe molto apprezzato.

Modifica: le immagini scelte dalla galleria vengono inviate al server dopo averlo ridimensionato alla dimensione richiesta.

Risposte:


144

Presumo che tu conosca il percorso e il nome file dell'immagine che desideri caricare. Aggiungi questa stringa al tuo NameValuePairutilizzo imagecome nome-chiave.

L'invio di immagini può essere effettuato utilizzando le librerie HttpComponents . Scarica l'ultimo binario HttpClient (attualmente 4.0.1 ) con pacchetto di dipendenze e copia apache-mime4j-0.6.jare httpmime-4.0.1.jarnel tuo progetto e aggiungili al tuo percorso di compilazione Java.

Dovrai aggiungere le seguenti importazioni alla tua 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;

Ora puoi creare un MultipartEntityper allegare un'immagine alla tua richiesta POST. Il codice seguente mostra un esempio di come eseguire questa operazione:

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

Spero che questo ti aiuti un po 'nella giusta direzione.


6
Lo consiglierei sicuramente. In questo modo probabilmente puoi usare le funzionalità di Django per ricevere l'immagine e memorizzarla facilmente. Un altro modo sarebbe codificare il flusso di byte dall'immagine in una stringa codificata in base64 e decodificarlo sul lato server. Ma questa sarebbe una seccatura troppo secondo me e non la strada da percorrere.
Piro,

6
Ehi ragazzi, c'è un modo per farlo senza MultipartEntity? Davvero non voglio importare tutto Apache HC solo per quelle 4 classi. :-(
Neil Traft

6
Basta aggiungere un secondo parametro a FileBodycon il tipo Mime desiderato. Ad esempio:new FileBody(new File (nameValuePairs.get(index).getValue()), "image/jpeg")
Piro,

4
Sembra che la multipartualità sia deprecata?
Nanne,

1
@Piro Stavo pensando di modificare anche la tua risposta. L'entità multipart viene ammortizzata insieme alla versione del corpo della stringa che si sta utilizzando. Il motivo per cui non sto modificando è perché non ho potuto associare tutti i dati in namevaluepairs come hai fatto tu.
Argomento illegale

15

Codice aggiornato versione 4.3.5

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

Da allora MultipartEntityè stato deprecato . Si prega di consultare il codice qui sotto.

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

Quali pacchetti jar sono necessari?

3
httpclient-4.3.5.jar httpcore-4.3.2.jar httpmime-4.3.5.jar
AZ_11

Cosa restituisce addQueryParams?
San

11

La libreria loopj può essere utilizzata direttamente per questo scopo:

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/


5

Ho faticato molto nel tentativo di implementare la pubblicazione di un'immagine dal client Android al servlet usando httpclient-4.3.5.jar, httpcore-4.3.2.jar, httpmime-4.3.5.jar. Ho sempre avuto un errore di runtime. Ho scoperto che fondamentalmente non è possibile utilizzare questi vasi con Android poiché Google utilizza la versione precedente di HttpClient in Android. La spiegazione è qui http://hc.apache.org/httpcomponents-client-4.3.x/android-port.html . È necessario ottenere il vaso httpclientandroidlib-1.2.1 da libreria http-client di Android . Quindi modificare le importazioni da or.apache.http.client a ch.boye.httpclientandroidlib. Spero che questo ti aiuti.


-13

Di solito lo faccio nel thread gestendo la risposta json:

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

Se devi eseguire trasformazioni sull'immagine, ti consigliamo di creare un Drawable anziché un Bitmap.


3
La domanda è come pubblicare un'immagine e non come ottenerla.
dwbrito
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.