使用 Http Post 发送图像
Posted
技术标签:
【中文标题】使用 Http Post 发送图像【英文标题】:Sending images using Http Post 【发布时间】:2011-02-25 12:42:12 【问题描述】:我想使用 Http Post 将图像从 android 客户端发送到 Django 服务器。图片是从图库中选择的。目前,我正在使用列表值名称 Pairs 将必要的数据发送到服务器并接收来自 Django 的 JSON 响应。是否可以对图像使用相同的方法(在 JSON 响应中嵌入图像的 url)?
另外,哪种方法更好:远程访问图像而不从服务器下载它们或将它们下载并存储在位图数组中并在本地使用它们?图片数量少(
任何解决这些问题的教程将不胜感激。
编辑:从图库中选择的图像在缩放到所需大小后发送到服务器。
【问题讨论】:
【参考方案1】:我假设您知道要上传的图片的路径和文件名。使用 image
作为键名,将此字符串添加到您的 NameValuePair
。
可以使用HttpComponents libraries 发送图像。下载最新的 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();
我希望这对您有所帮助。
【讨论】:
我绝对会推荐这个。这样,您可能可以使用 Django 功能来接收图像并轻松存储它。另一种方法是将图像中的字节流编码为 base64 编码字符串并在服务器端对其进行解码。但在我看来,这太麻烦了,而且不是要走的路。 嘿伙计们,没有 MultipartEntity 有没有办法做到这一点?我真的不想只为这 4 个类导入所有 Apache HC。 :-( 只需将第二个参数添加到FileBody
并使用您想要的 Mime 类型。例如:new FileBody(new File (nameValuePairs.get(index).getValue()), "image/jpeg")
看起来多方已被弃用?
@Piro 我也在考虑编辑你的答案。多部分实体与您使用的字符串正文版本一起折旧。我不编辑的原因是因为我无法像您所做的那样绑定名称值对中的所有数据。【参考方案2】:
httpclient-4.3.5.jar httpcore-4.3.2.jar httpmime-4.3.5.jar4.3.5 版更新代码
由于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();
【讨论】:
需要哪些jar包? httpclient-4.3.5.jar httpcore-4.3.2.jar httpmime-4.3.5.jar addQueryParams 返回什么?【参考方案3】: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/
【讨论】:
【参考方案4】:我在尝试使用 httpclient-4.3.5.jar、httpcore-4.3.2.jar、httpmime-4.3.5.jar 将图像从 Android 客户端发布到 servlet 时遇到了很多困难。我总是遇到运行时错误。我发现基本上你不能在 Android 上使用这些 jar,因为 Google 在 Android 中使用的是旧版本的 HttpClient。解释在这里http://hc.apache.org/httpcomponents-client-4.3.x/android-port.html。您需要从android http-client library 获取httpclientandroidlib-1.2.1 jar。然后将您的导入从 or.apache.http.client 更改为 ch.boye.httpclientandroidlib。希望这会有所帮助。
【讨论】:
【参考方案5】:我通常在处理 json 响应的线程中这样做:
try
Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(imageUrl).getContent());
catch (MalformedURLException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
如果您需要对图像进行转换,则需要创建 Drawable 而不是 Bitmap。
【讨论】:
问题是如何发布图片,而不是如何获取。以上是关于使用 Http Post 发送图像的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 C 中的 HTTP POST 请求发送图像或二进制数据