使用Base64将Android映像上传/下载到JSON会导致内存不足错误

时间:2016-01-20 16:48:58

标签: android image base64 gson android-volley

我目前正在编码和解码图像到Base64。我通过使用流将图像编码为字符串来克服OOM的初始问题。

我现在的问题是我无法理解如何通过Gson将多个分辨率图像(5620 x 3747 - 4.92MB或3264 x 1836 - 1.35MB)的多个Base64编码字符串添加到JSON对象。目前Gson仅使用来自5312 x 2988 - 4.95 MB图像的2个Base64字符串抛出OOM异常。

我知道android可能只能为每个应用程序节省16 / 20Mb,因此这种转换必须超过限制。

如何将流中的Base64字符串写入JSON对象,该对象将包含发布到我的服务器所需的特定值?

更改我的服务器以接受多部分请求而不是基于JSON的POJO以及多个Base64字符串会更容易吗?我目前使用的是Volley,并且没有官方的多部分请求以及IO流媒体。

如果是压缩问题,在编码为Base64字符串之前,我应该对图像应用多少压缩?理想情况下,我希望失去任何质量但具有最佳压缩级别。

更多信息

我正在上传多个不同分辨率的图片,因为它是兼容性的测试。例如,我发送的所有图像都是在低分辨率和极高分辨率的设备上拍摄的,因为我的应用依赖于这些图像的功能。我试图证明我的应用程序可以处理任何图像(在某种程度上,主要是在移动设备上捕获的图像)。

据我所知,某些图像可能太大,以至于将它们加载到内存中会导致异常。这是我稍后会尝试处理的事情。

在某些情况下,将上传的图片可以从1到200。

我正在努力寻找能够很好扩展的最佳解决方案。

2 个答案:

答案 0 :(得分:2)

  

...适用于多种分辨率图像(5620 x 3747 - 4.92MB或3264 x 1836 - 1.35MB)......

不确定这是在内存中分配图像所需的文件大小还是内存,但要看一下以下链接:http://www.scantips.com/basics1d.html,我看到了:

  

对于4000 x 2500像素的图像,

     

然后:4000 x 2500像素= 4000x2500 = 10百万像素

     

4000x2500 x 3 = 3000万字节(如果是24位RGB)

     

30,000,000字节/(1024 x 1024)= 28.61兆字节(MB)

     

这就是数据的大小 - 适用于任何24位1000万像素   图像,但JPG文件将其压缩得更小(仅在文件中)。

我认为您处理的图像所记忆的图像比您预期的要多得多。

另外,看看这个问题并回答:https://stackoverflow.com/a/11402374/3393666,我们知道图像的base64表示比原始图像大小占用的内存多37%。

  

如何将流中的Base64字符串写入JSON对象,该对象将包含发布到我的服务器所需的特定值?

我认为你可以通过简单地在JSON对象中添加图像的base64表示然后将其发布到服务器来做到这一点(小图像不是大图像)。

  

将服务器更改为接受多部件请求而不是基于JSON的POJO以及多个Base64字符串会更容易吗?

在我看来,这是实施你想要实现的目标的最佳选择。

  

我目前使用的是Volley,并且没有正式的多部分请求以及IO流式传输。

你可以看一下这个答案:https://stackoverflow.com/a/16803473/3393666,你绝对可以通过排球来做到这一点,但如果你想要一个替代方案你可以尝试改装(http://square.github.io/retrofit/)他们支持我们的盒子。

例如:

@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description); 

答案 1 :(得分:2)

我研究了使用Volley作为将大型JSON对象传输到服务器的机制,并找到了这个answer。这个答案基本上证明了Volley对我想要的东西是个坏主意。

我切换到OkHttp,现在使用他们的流方法,允许将JSON流式传输到服务器,然后使用简化的方法读取响应。我使用GSON库来解析响应,因为OKHttp允许将响应JSON / Object流式传输到读取器对象中,然后Gson将其用于内部流式传输并解析为POJO类。

我没有切换到多部件请求的原因是服务器端实现严格且不可更改以覆盖多部件请求,它严格要求数据和文件的JSON表示。

为了在Android上处理Base64图像,我严格意味着使用String表示,只是转换为字节以节省使用过多的内存。我阅读了有关String内存使用和管理的this文章。使用字节,您可以轻松传输数据,而不会在内存上留下大量空间。

对于显示图像,我仍然使用图像库Glide来避免字节到字符串的转换。它们允许您传递一个非常方便的byte[]