2016-01-20 133 views
11

我目前编码和解码图像到Base64。我利用流将图像编码为字符串,克服了OOM的最初问题。安卓图像上传/下载与Base64到JSON导致内存不足错误

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

据我所知,android可能只能够为每个应用程序腾出16/20Mb,所以这个转换必须超出限制。

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

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

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

位的更多信息

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

我知道一些图像可能会很大,以至于将它们加载到内存中会导致异常。这是我稍后会尝试和处理的。

在某些情况下,将被上传可以从1〜200

我试图寻找最优的解决方案,将很好地扩展跨越图像。

+0

如果你想使用Mutipart Request和Volley,IMO,你可以参考我的示例代码https://github.com/ngocchung/VolleyNoApache/blob/master/app/src/main/java/com/example/ volleynoapache/MultipartActivity.java。在@ kevinkl3答案,http://stackoverflow.com/a/16803473/3393666我也有一个答案 – BNK

回答

2

我看着用乱射作为一种机制来运输大型JSON对象到服务器,发现这个answer。这个回答基本上证明了,Volley对于我想要的是一个坏主意。

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

我没有切换到多部分请求的原因是由于服务器端的实现是严格的并且不可更改以涵盖多部分请求,因此严格地期望数据和文件的JSON表示。

有关的Android处理的Base64图像I严重reccomend 使用String表示和仅仅转换为字节,以节省使用的存储器过量。我阅读this关于String内存使用和管理的文章。使用字节,您可以轻松传输数据,而不会在内存上留下大量的空间。

用于显示图像我仍然通过使用图像库Glide避免字节转换为字符串。他们允许你通过一个byte[]这是巨大的便利。

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×3 = 30万个字节(如果24位RGB)

30000000字节/(1024×1024)= 28.61兆字节(MB)

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

我认为你正在处理的图像比你想象的要多得多。

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

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

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

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

在我看来,这将是你最好的选择来实现你想要实现的。

我目前使用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); 
相关问题