Gửi hình ảnh bằng cách sử dụng bài viết http


129

Tôi muốn gửi một hình ảnh từ máy khách Android đến máy chủ Django bằng cách sử dụng http Post. Hình ảnh được chọn từ bộ sưu tập. Hiện tại, tôi đang sử dụng cặp giá trị danh sách Cặp để gửi dữ liệu cần thiết đến máy chủ và nhận phản hồi từ Django trong JSON. Cách tiếp cận tương tự có thể được sử dụng cho hình ảnh (với url cho hình ảnh được nhúng trong phản hồi JSON) không?

Ngoài ra, phương pháp nào tốt hơn: truy cập hình ảnh từ xa mà không cần tải xuống từ máy chủ hoặc tải xuống và lưu trữ chúng trong mảng Bitmap và sử dụng chúng cục bộ? Các hình ảnh có số lượng ít (<10) và kích thước nhỏ (50 * 50 nhúng).

Bất kỳ hướng dẫn để giải quyết những vấn đề này sẽ được nhiều đánh giá cao.

Chỉnh sửa: Hình ảnh được chọn từ thư viện được gửi đến máy chủ sau khi thu nhỏ kích thước theo yêu cầu.

Câu trả lời:


144

Tôi sẽ giả định rằng bạn biết đường dẫn và tên tệp của hình ảnh mà bạn muốn tải lên. Thêm chuỗi này để NameValuePairsử dụng imagelàm tên khóa.

Gửi hình ảnh có thể được thực hiện bằng cách sử dụng các thư viện HttpComponents . Tải xuống tệp nhị phân httpClient (hiện tại 4.0.1 ) mới nhất với gói phụ thuộc và sao chép apache-mime4j-0.6.jarhttpmime-4.0.1.jarvào dự án của bạn và thêm chúng vào đường dẫn xây dựng Java của bạn.

Bạn sẽ cần thêm các mục nhập sau vào lớp của bạn.

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;

Bây giờ bạn có thể tạo một MultipartEntityđể đính kèm một hình ảnh vào yêu cầu POST của bạn. Đoạn mã sau đây cho thấy một ví dụ về cách thực hiện việc này:

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

Tôi hy vọng điều này sẽ giúp bạn một chút đi đúng hướng.


6
Tôi chắc chắn sẽ khuyên bạn điều này. Bằng cách này, bạn có thể có thể sử dụng các tính năng Django để nhận hình ảnh và lưu trữ dễ dàng. Một cách khác là mã hóa luồng byte từ hình ảnh sang chuỗi được mã hóa base64 và giải mã phía máy chủ. Nhưng điều này sẽ là quá nhiều rắc rối trong quan điểm của tôi và không phải là cách để đi.
Piro

6
Này các bạn, có cách nào để làm điều này mà không có MultipartEntity không? Tôi thực sự không muốn nhập tất cả Apache HC chỉ cho 4 lớp đó. :-(
Neil Traft

6
Chỉ cần thêm một tham số thứ 2 FileBodyvới Loại Mime mong muốn của bạn. Ví dụ:new FileBody(new File (nameValuePairs.get(index).getValue()), "image/jpeg")
Piro

4
Có vẻ như đa nhân bị phản đối?
Nanne

1
@Piro Tôi đã suy nghĩ về việc chỉnh sửa câu trả lời của bạn. Thực thể nhiều phần được khấu hao cùng với phiên bản thân chuỗi mà bạn đang sử dụng. Lý do tôi không chỉnh sửa là vì tôi không thể liên kết tất cả dữ liệu trong namevaluepairs như bạn đã làm.
Tranh luận bất hợp pháp

15

Phiên bản 4.3.5 Mã cập nhật

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

MultipartEntityđã bị phản đối . Xin vui lòng xem mã dưới đây.

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

Những gói jar là cần thiết?

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

AddQueryParams trả về cái gì?
San

11

Các loopj thư viện có thể được sử dụng thẳng về phía trước cho mục đích này:

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

Tôi đã vật lộn rất nhiều khi cố gắng thực hiện việc đăng một hình ảnh từ máy khách Android lên servlet bằng cách sử dụng httpclient-4.3.5.jar, httpcore-4.3.2.jar, httpmime-4.3.5.jar. Tôi luôn luôn có một lỗi thời gian chạy. Tôi phát hiện ra rằng về cơ bản, bạn không thể sử dụng các lọ này với Android vì Google đang sử dụng phiên bản cũ hơn của httpClient trong Android. Giải thích ở đây http://hc.apache.org/httpcomponents-client-4.3.x/android-port.html . Bạn cần lấy jar httpclientandroidlib-1.2.1 từ thư viện http-client của android . Sau đó thay đổi nhập khẩu của bạn từ or.apache.http.client thành ch.boye.httpclientandroidlib. Hi vọng điêu nay co ich.


-13

Tôi thường làm điều này trong luồng xử lý phản hồi json:

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

Nếu bạn cần thực hiện các biến đổi trên hình ảnh, bạn sẽ muốn tạo một Drawable thay vì Bitmap.


3
Câu hỏi là làm thế nào để đăng một hình ảnh, và không làm thế nào để có được nó.
dwbrito
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.