Android 使用 Base64 的图像 upload/download 转换为 JSON 导致内存不足错误
Android Image upload/download with Base64 into JSON causes Out of memory error
我目前将图像编码和解码为 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 对象,该对象将包含 post 到我的服务器所需的特定值?
将我的服务器更改为接受多部分请求而不是具有多个 Base64 字符串的基于 JSON 的 POJO 会更容易吗?我目前使用 Volley,但没有官方的多部分请求和 IO 流。
如果是压缩问题,在编码为 Base64 字符串之前我应该对图像应用多少压缩?理想情况下,我希望几乎不损失任何质量但具有最佳压缩级别。
更多信息
我正在上传多张不同分辨率的图片,因为这是为了测试兼容性。例如,我发送的所有图像都是在低分辨率和极高分辨率设备上拍摄的,因为我的应用程序依赖于这些图像来实现功能。我试图证明我的应用程序可以处理任何图像(在某种程度上,主要是在移动设备上捕获的图像)。
我了解到有些图片可能太大,加载到内存中会出现异常。这是我稍后会尝试处理的事情。
在某些情况下,将要上传的图像可以跨越 1 到 200。
我正在尝试寻找可以很好扩展的最佳解决方案。
... for multiple resolutions images (5620 x 3747 - 4.92MB or 3264 x 1836 - 1.35MB)...
不确定这是文件大小还是在内存中分配图像所需的内存,但看看下面的 link:http://www.scantips.com/basics1d.html,我看到了这个:
For a 4000 x 2500 pixel image,
then: 4000 x 2500 pixels = 4000x2500 = 10 megapixels
4000x2500 x 3 = 30 million bytes (if 24-bit RGB)
30,000,000 bytes / (1024 x 1024) = 28.61 megabytes (MB)
This is simply how large the data is - For ANY 24-bit 10 megapixel
image, but JPG files compress it smaller (only while in the file).
我认为您正在处理的图像占用的内存比您预期的要多。
此外,看看这个问题和答案:,我们知道图像的 base64 表示比原始图像大小多占用 37% 的内存。
How can I write the Base64 String in a stream to a JSON object that will contain the specific values needed to post into my server?
我认为您可以通过简单地在 JSON 对象中添加图像的 base64 表示,然后将其发布到服务器来做到这一点(使用小图像而不是大图像)。
Would it be easier to change my server to accept a Multi-Part request instead of a JSON based POJO with multiple Base64 Strings?
在我看来,这是实现您想要实现的目标的最佳选择。
I currently use Volley and there isn't an official Multi-Part Request as well as IO streaming.
你可以看看这个答案:, you can definitely can do it with volley, but if you want an alternative you can try with retrofit (http://square.github.io/retrofit/) 他们支持 Multipart our of the box。
例如:
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
我研究了使用 Volley 作为将大型 JSON 对象传输到服务器的机制,并发现了这个 answer。这个答案基本上证明了 Volley 对我想要的东西来说不是一个好主意。
我切换到 OkHttp,现在使用他们的流式传输方法,允许将 JSON 流式传输到服务器,然后使用简化的方法读取响应。我使用 GSON 库来解析响应,因为 OKHttp 允许将响应 JSON/Object 流式传输到 reader 对象中,然后 Gson 使用该对象进行内部流式传输并解析为 POJO class.
我没有切换到多部分请求的唯一原因是服务器端实现是严格且不可更改的以涵盖多部分请求,它严格期望数据的 JSON 表示和文件。
为了在 Android 上处理 Base64 图像,我强烈建议 不要 使用 String
表示并仅转换为字节以节省使用过多的记忆。我阅读了 this 篇关于 String
内存使用和管理的文章。使用 Bytes,您可以轻松传输数据,而不会占用大量内存。
为了显示图像,我仍然使用图像库 Glide 来避免字节到字符串的转换。它们允许您传入一个非常方便的 byte[]
。
我目前将图像编码和解码为 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 对象,该对象将包含 post 到我的服务器所需的特定值?
将我的服务器更改为接受多部分请求而不是具有多个 Base64 字符串的基于 JSON 的 POJO 会更容易吗?我目前使用 Volley,但没有官方的多部分请求和 IO 流。
如果是压缩问题,在编码为 Base64 字符串之前我应该对图像应用多少压缩?理想情况下,我希望几乎不损失任何质量但具有最佳压缩级别。
更多信息
我正在上传多张不同分辨率的图片,因为这是为了测试兼容性。例如,我发送的所有图像都是在低分辨率和极高分辨率设备上拍摄的,因为我的应用程序依赖于这些图像来实现功能。我试图证明我的应用程序可以处理任何图像(在某种程度上,主要是在移动设备上捕获的图像)。
我了解到有些图片可能太大,加载到内存中会出现异常。这是我稍后会尝试处理的事情。
在某些情况下,将要上传的图像可以跨越 1 到 200。
我正在尝试寻找可以很好扩展的最佳解决方案。
... for multiple resolutions images (5620 x 3747 - 4.92MB or 3264 x 1836 - 1.35MB)...
不确定这是文件大小还是在内存中分配图像所需的内存,但看看下面的 link:http://www.scantips.com/basics1d.html,我看到了这个:
For a 4000 x 2500 pixel image,
then: 4000 x 2500 pixels = 4000x2500 = 10 megapixels
4000x2500 x 3 = 30 million bytes (if 24-bit RGB)
30,000,000 bytes / (1024 x 1024) = 28.61 megabytes (MB)
This is simply how large the data is - For ANY 24-bit 10 megapixel image, but JPG files compress it smaller (only while in the file).
我认为您正在处理的图像占用的内存比您预期的要多。
此外,看看这个问题和答案:,我们知道图像的 base64 表示比原始图像大小多占用 37% 的内存。
How can I write the Base64 String in a stream to a JSON object that will contain the specific values needed to post into my server?
我认为您可以通过简单地在 JSON 对象中添加图像的 base64 表示,然后将其发布到服务器来做到这一点(使用小图像而不是大图像)。
Would it be easier to change my server to accept a Multi-Part request instead of a JSON based POJO with multiple Base64 Strings?
在我看来,这是实现您想要实现的目标的最佳选择。
I currently use Volley and there isn't an official Multi-Part Request as well as IO streaming.
你可以看看这个答案:, you can definitely can do it with volley, but if you want an alternative you can try with retrofit (http://square.github.io/retrofit/) 他们支持 Multipart our of the box。
例如:
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
我研究了使用 Volley 作为将大型 JSON 对象传输到服务器的机制,并发现了这个 answer。这个答案基本上证明了 Volley 对我想要的东西来说不是一个好主意。
我切换到 OkHttp,现在使用他们的流式传输方法,允许将 JSON 流式传输到服务器,然后使用简化的方法读取响应。我使用 GSON 库来解析响应,因为 OKHttp 允许将响应 JSON/Object 流式传输到 reader 对象中,然后 Gson 使用该对象进行内部流式传输并解析为 POJO class.
我没有切换到多部分请求的唯一原因是服务器端实现是严格且不可更改的以涵盖多部分请求,它严格期望数据的 JSON 表示和文件。
为了在 Android 上处理 Base64 图像,我强烈建议 不要 使用 String
表示并仅转换为字节以节省使用过多的记忆。我阅读了 this 篇关于 String
内存使用和管理的文章。使用 Bytes,您可以轻松传输数据,而不会占用大量内存。
为了显示图像,我仍然使用图像库 Glide 来避免字节到字符串的转换。它们允许您传入一个非常方便的 byte[]
。