如何使用HTTP POST和JSON将大图像/照片发送到服务器?我尝试了几种方法,但所有方法都不好(OutOfMemory Exceptions等)。
“经典”代码:
Bitmap image;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, stream);
image.recycle();
image = null;
byte[] byteArray = stream.toByteArray();
try {
stream.close();
} catch (IOException e1) {
}
stream = null;
String encoded = Base64.encodeToString(byteArray,
Base64.DEFAULT);
HttpClient httpClient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(Globals.URL + "/storageUploadFile");
httppost.setHeader("Token", Globals.Token);
String msg = "";
try {
JSONObject jo = new JSONObject();
jo.put("fileName", fileName);
jo.put("content", encoded);
httppost.setEntity(new StringEntity(jo.toString());
HttpResponse response = httpClient.execute(httppost);
HttpEntity httpentity = response.getEntity();
msg = EntityUtils.toString(httpentity);
//...
在此代码中,我在此处获得例外:httppost.setEntity(new StringEntity(jo.toString());
图像保存在存储卡上。您建议上传图片什么?通过块发送图像块?我宁愿把它作为一个“项目”发送。我希望2 MB不是那么大。我的API有参数“content”,它是base64编码的图像。将图像转换为base64是一种好方法吗?
答案 0 :(得分:2)
如果你真的需要json,如果你真的需要base64,你需要流式传输而不是将所有转换保存在内存中。如果您的图像是2Mb,则在您的方法中使用:
对于一个简单的2MB图像,这总计超过11MB。
第一步是使用Json流API(我使用Jackson)
像这样:
// The original size prevents automatic resizing which would take twice the memory
ByteArrayOutputStream baos = new ByteArrayOutputStream(byteArray.length * 1.2);
JsonGenerator jo = new JsonFactory().createGenerator(baos);
jo.writeStartObject();
jo.writeStringField("fileName", fileName);
// Jackson takes care of the base64 encoding for us
jo.writeBinaryField("content", byteArray);
jo.writeEndObject();
httppost.setEntity(new ByteArrayEntity(baos.toByteArray());
在这种情况下,我们仅在内存byteArray
和baos
中保留其基础byte[]
,理论总数为2MB + 1.2*2MB = 4.4MB
(仅使用字符串表示,仅1个中间字节[])。请注意,流式传输到byte []的base64由Jackson完全透明地完成。
如果仍有内存问题(例如,如果要发送10MB图像),则需要将内容直接流式传输到连接。为此,您可以使用HttpUrlConnection并使用connection.getOutputStream()
作为createGenerator
的参数。