Android - 将编码图像(1 - 2 MB)上传到base64到服务器HTTP POST - JSON

时间:2014-05-23 15:51:02

标签: android json image http image-uploading

如何使用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是一种好方法吗?

1 个答案:

答案 0 :(得分:2)

如果你真的需要json,如果你真的需要base64,你需要流式传输而不是将所有转换保存在内存中。如果您的图像是2Mb,则在您的方法中使用:

  • 2MB的字节
  • 对于base64字符串为4.6MB(java字符串在内部表示为chars,为16位)
  • 对于String实体中的JSONObject.toString结果为4.6MB

对于一个简单的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());

在这种情况下,我们仅在内存byteArraybaos中保留其基础byte[],理论总数为2MB + 1.2*2MB = 4.4MB(仅使用字符串表示,仅1个中间字节[])。请注意,流式传输到byte []的base64由Jackson完全透明地完成。

如果仍有内存问题(例如,如果要发送10MB图像),则需要将内容直接流式传输到连接。为此,您可以使用HttpUrlConnection并使用connection.getOutputStream()作为createGenerator的参数。