Enviando imagens usando Http Post

129

Quero enviar uma imagem do cliente Android para o servidor Django usando o Http Post. A imagem é escolhida da galeria. No momento, estou usando o nome do valor da lista Pairs para enviar os dados necessários para o servidor e recebendo respostas do Django no JSON. A mesma abordagem pode ser usada para imagens (com URLs para imagens incorporadas nas respostas JSON)?

Além disso, qual é o melhor método: acessar imagens remotamente sem baixá-las do servidor ou baixá-las e armazená-las em uma matriz Bitmap e usá-las localmente? As imagens são poucas em número (<10) e pequenas em tamanho (50 * 50 mergulhos).

Qualquer tutorial para resolver esses problemas seria muito apreciado.

Editar: as imagens escolhidas na galeria são enviadas para o servidor depois de dimensionadas para o tamanho necessário.

Pappachan Primevo
fonte

Respostas:

144

Vou assumir que você conhece o caminho e o nome do arquivo da imagem que deseja enviar. Adicione esta string ao seu NameValuePairuso imagecomo o nome da chave.

O envio de imagens pode ser feito usando as bibliotecas HttpComponents . Faça o download do último binário HttpClient (atualmente 4.0.1 ) com dependências, pacote e cópia apache-mime4j-0.6.jare httpmime-4.0.1.jarno seu projeto e adicione-os ao seu caminho de construção Java.

Você precisará adicionar as seguintes importações à sua 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;

Agora você pode criar um MultipartEntitypara anexar uma imagem à sua solicitação POST. O código a seguir mostra um exemplo de como fazer isso:

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 isso ajude você na direção certa.

Piro
fonte
6
Definitivamente, eu recomendaria isso. Dessa forma, você provavelmente pode usar os recursos do Django para receber a imagem e armazená-la facilmente. Uma outra maneira seria codificar o fluxo de bytes da imagem para uma cadeia codificada em base64 e decodificá-la no servidor. Mas isso seria muito complicado na minha opinião e não o caminho a percorrer.
Piro 30/05
6
Ei pessoal, existe alguma maneira de fazer isso sem MultipartEntity? EU REALMENTE não quero importar todo o Apache HC apenas para essas 4 classes. :-(
Neil Traft
6
Basta adicionar um segundo parâmetro ao FileBodytipo de mímica desejado. Exemplo:new FileBody(new File (nameValuePairs.get(index).getValue()), "image/jpeg")
Piro 08/03
4
Parece que a multipartidade está obsoleta?
precisa saber é
1
@Piro Também estava pensando em editar sua resposta. A entidade multipartes é depreciada junto com a versão do corpo da sequência que você está usando. A razão pela qual não estou editando é porque não foi possível vincular todos os dados em namevaluepairs como você fez.
Argumento ilegal
15

Código atualizado da versão 4.3.5

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

Desde MultipartEntityque foi preterido . Por favor veja o código abaixo.

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_
fonte
Quais pacotes jar são necessários?
3
httpclient-4.3.5.jar httpcore-4.3.2.jar httpmime-4.3.5.jar
AZ_
O que addQueryParams retorna?
San
11

A biblioteca loopj pode ser usada diretamente para esta finalidade:

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

Eu lutei bastante tentando implementar a postagem de uma imagem do cliente Android para o servlet usando httpclient-4.3.5.jar, httpcore-4.3.2.jar, httpmime-4.3.5.jar. Eu sempre recebia um erro de tempo de execução. Eu descobri que basicamente você não pode usar esses frascos com Android, pois o Google está usando a versão mais antiga do HttpClient no Android. A explicação está aqui http://hc.apache.org/httpcomponents-client-4.3.x/android-port.html . Você precisa obter o jar httpclientandroidlib-1.2.1 da biblioteca cliente http android . Altere suas importações de or.apache.http.client para ch.boye.httpclientandroidlib. Espero que isto ajude.

DavidC
fonte
-13

Eu costumo fazer isso no segmento de manipulação da resposta json:

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

Se você precisar fazer transformações na imagem, crie um Drawable em vez de um Bitmap.

Dylan McClung
fonte
3
A questão é como postar uma imagem, e não como obtê-la.
precisa saber é