Отправка изображений с помощью Http Post

129

Я хочу отправить изображение с клиента Android на сервер Django с помощью Http Post. Изображение выбрано из галереи. В настоящее время я использую имя значения списка Pairs для отправки необходимых данных на сервер и получения ответов от Django в формате JSON. Можно ли использовать тот же подход для изображений (с URL-адресами изображений, встроенными в ответы JSON)?

Кроме того, что является лучшим методом: удаленный доступ к изображениям без их загрузки с сервера или загрузка и сохранение их в массиве Bitmap и их локальное использование? Изображения немногочисленны (<10) и имеют небольшой размер (угол наклона 50 * 50).

Мы будем очень признательны за любой учебник по решению этих проблем.

Изменить: изображения, выбранные из галереи, отправляются на сервер после масштабирования до необходимого размера.

Первобытный Паппачан
источник

Ответы:

144

Я предполагаю, что вы знаете путь и имя файла изображения, которое хотите загрузить. Добавьте эту строку к своему NameValuePairиспользованию в imageкачестве имени ключа.

Отправку изображений можно выполнить с помощью библиотек HttpComponents . Загрузите последний двоичный файл HttpClient (в настоящее время 4.0.1 ) с пакетом зависимостей, скопируйте apache-mime4j-0.6.jarиhttpmime-4.0.1.jar в свой проект и добавить их в свой путь сборки Java.

Вам нужно будет добавить в свой класс следующие элементы импорта.

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;

Теперь вы можете создать, MultipartEntityчтобы прикрепить изображение к вашему запросу POST. В следующем коде показан пример того, как это сделать:

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

Надеюсь, это немного поможет вам в правильном направлении.

Пиро
источник
6
Я определенно рекомендую это. Таким образом, вы, вероятно, сможете использовать функции Django, чтобы легко получать изображение и сохранять его. Еще один способ - закодировать поток байтов из изображения в строку, закодированную в base64, и декодировать ее на стороне сервера. Но, на мой взгляд, это было бы слишком хлопотно, и это не лучший вариант.
Пиро
6
Привет, ребята, есть ли способ сделать это без MultipartEntity? Я ДЕЙСТВИТЕЛЬНО не хочу импортировать весь Apache HC только для этих 4 классов. :-(
Нил Трафт 01
6
Просто добавьте второй параметр FileBodyс желаемым типом Mime. Например:new FileBody(new File (nameValuePairs.get(index).getValue()), "image/jpeg")
Piro
4
Похоже, что многопартийность устарела?
Nanne
1
@Piro Я тоже думал отредактировать твой ответ. Сущность Multipart обесценивается вместе с версией тела строки, которую вы используете. Причина, по которой я не редактирую, заключается в том, что я не мог связать все данные в парах namevaluepairs, как это сделали вы.
Illegal Argument
15

Версия 4.3.5 Обновленный код

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

Поскольку MultipartEntityбыл объявлен устаревшим . Пожалуйста, посмотрите код ниже.

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_
источник
Какие пакеты jar нужны?
3
httpclient-4.3.5.jar httpcore-4.3.2.jar httpmime-4.3.5.jar
AZ_
Что возвращает addQueryParams?
Сан,
11

Для этой цели можно использовать библиотеку loopj :

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
источник
5

Я изо всех сил пытался реализовать отправку изображения из клиента Android в сервлет с использованием httpclient-4.3.5.jar, httpcore-4.3.2.jar, httpmime-4.3.5.jar. У меня всегда возникала ошибка выполнения. Я обнаружил, что в основном вы не можете использовать эти банки с Android, поскольку Google использует более старую версию HttpClient в Android. Объяснение здесь http://hc.apache.org/httpcomponents-client-4.3.x/android-port.html . Вам необходимо получить банку httpclientandroidlib-1.2.1 из библиотеки http-client для Android . Затем измените импорт с or.apache.http.client на ch.boye.httpclientandroidlib. Надеюсь это поможет.

DavidC
источник
-13

Обычно я делаю это в потоке, обрабатывающем json-ответ:

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

Если вам нужно преобразовать изображение, вы захотите создать Drawable вместо Bitmap.

Дилан МакКланг
источник
3
Вопрос в том, как разместить изображение, а не в том, как его получить.
dwbrito 04