使用改进流式传输base64图像

时间:2017-06-20 07:34:16

标签: android gson retrofit2 okhttp

我有一个上游服务器,它接受使用rest的图像提交。提交的图像是与此类似的JSON有效负载的一部分

{
  "name": "Blah.jpg",
  "uploader": "user1",
  "image": "<base64.....>"
}

使用此策略适用于小图像,但在较大图像上会产生内存不足错误。

是否可以流式传输图像的base64组件?传入类似迭代器的东西,用于读取图像块,将它们直接发送到网络中?

2 个答案:

答案 0 :(得分:1)

不是Gson或Moshi。这两个库在将它们发送到流之前需要字符串在内存中。

答案 1 :(得分:0)

我在扩展okhttp3.RequestBody

的类中使用以下内容解决了这个问题
private void writeFile(File file, BufferedSink sink) throws IOException {
    byte buf[] = new byte[3000];
    try (FileInputStream fin = new FileInputStream(file)) {
        while (fin.read(buf) >= 0) {
            byte encoded[] = Base64.encodeBase64(buf);
            sink.write(encoded);
        }
    }
}

它使用 Android&#39; android.util.Base64 Apache Commons&#39; org.apache.commons.codec.binary.Base64对缓冲的数据块进行编码。

我最后分别编写了其他json字段,其粒度足以让我可以将文件记录准确地插入到我需要的位置。

编辑:

正如您在上面的编辑中所看到的,我最终通过commons-codec文件中的compile 'commons-codec:commons-codec:1.5'切换到了Apache build.gradle

我没有时间研究为什么Android SDK解决方案无效。我按照其他地方的建议尝试了他们的Base64.encode(buf, Base64.NO_WRAP) - 据说相当于Apache Commons&#39; encodeBase64(byte[]) - 但这不起作用,因此转换。

问题本来可以在我们的后端,所以不要仅根据我的帖子排除Android SDK的解决方案 - 我只是想添加这个注释,以便读者可以看到实际工作的代码片段对我来说最终。